diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 5f3d953a9d8..4c5f1764094 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,6 +9,7 @@ Describe changes proposed in this pull request: - [ ] Has tests or has a separate issue that describes the types of test that should be created. If no test is included it should explicitly be mentioned in the PR why there is no test. - [ ] The commit log is comprehensible. It follows [7 rules of great commit messages](http://chris.beams.io/posts/git-commit/). For most PRs a single commit should suffice, in some cases multiple topical commits can be useful. During review it is ok to see tiny commits (e.g. Fix reviewer comments), but right before the code gets merged to master or rc branch, any such commits should be squashed since they are useless to the other developers. Definitely avoid [merge commits, use rebase instead.](http://nathanleclaire.com/blog/2014/09/14/dont-be-scared-of-git-rebase/) - [ ] Is this PR adding logic based on one or more **clinical** attributes? If yes, please make sure validation for this attribute is also present in the data validation / data loading layers (in backend repo) and documented in [File-Formats Clinical data section](https://github.com/cBioPortal/cbioportal/blob/master/docs/File-Formats.md#clinical-data)! +- [ ] Make sure your PR has one of the labels defined in https://github.com/cBioPortal/cbioportal/blob/master/.github/release-drafter.yml # Any screenshots or GIFs? If this is a new visual feature please add a before/after screenshot or gif diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 006a1c40dc7..7bf80ceff71 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -43,6 +43,10 @@ categories: labels: - 'documentation' - 'cl-documentation' + - title: '🖊️ Data Importer & Validator' + labels: + - 'importer' + - 'validator' - title: '🧹 Cleanup & Refactoring 🔧' labels: - 'cleanup' @@ -79,4 +83,4 @@ template: | - Frontend: https://github.com/cBioPortal/cbioportal-frontend/compare/$PREVIOUS_TAG...v$NEXT_PATCH_VERSION ## 🏷Notes on versioning and release procedure - https://docs.cbioportal.org/4.-development/release-procedure#a-note-on-versioning + https://docs.cbioportal.org/development/release-procedure/#a-note-on-versioning diff --git a/.github/workflows/dockerimage.yml b/.github/workflows/dockerimage.yml index 53f9d355e25..70ee5e1c6b0 100644 --- a/.github/workflows/dockerimage.yml +++ b/.github/workflows/dockerimage.yml @@ -5,6 +5,7 @@ on: - master - release-* - rc + - rfc* - demo-* - fusion-sv-migration - redis-branch-up-to-date diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 7e32fa444b6..57ca628fc14 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -42,10 +42,12 @@ jobs: working-directory: ./cbioportal-docker-compose run: | cd ./data && ./init.sh && rm -rf ./studies/* && cd ../config && \ - cat $PORTAL_SOURCE_DIR/portal/target/portal/WEB-INF/classes/portal.properties | \ - sed 's/db.host=.*/db.host=cbioportal-database:3306/g' | \ - sed 's|db.connection_string=.*|db.connection_string=jdbc:mysql://cbioportal-database:3306/|g' \ - > portal.properties + cat $PORTAL_SOURCE_DIR/portal/target/classes/portal.properties | \ + sed 's|db.host=.*||' | \ + sed 's|db.portal_db_name=.*||' | \ + sed 's|db.use_ssl=.*||' | \ + sed 's|db.connection_string=.*|db.connection_string=jdbc:mysql://cbioportal-database:3306/cbioportal?useSSL=false\&allowPublicKeyRetrieval=true|' \ + > portal.properties && more portal.properties - name: 'Start cbioportal-docker-compose' working-directory: ./cbioportal-docker-compose run: | diff --git a/.github/workflows/label-check.yml b/.github/workflows/label-check.yml new file mode 100644 index 00000000000..ceb4c8b7934 --- /dev/null +++ b/.github/workflows/label-check.yml @@ -0,0 +1,50 @@ +# This GitHub Actions workflow is designed to automatically check pull requests in the cBioPortal repository for valid labels before they can be merged. +# The workflow ensures that pull requests have labels that are defined in the .github/release-drafter.yml file's "categories" section. +# If a pull request lacks a valid label, the workflow will fail, preventing the merge until valid labels are applied. +name: Label Check + +on: + pull_request: + types: + - opened + - synchronize + +jobs: + label-check: + runs-on: ubuntu-latest + steps: + - name: Check PR Labels + uses: actions/checkout@v2 + + - name: Install dependencies + run: | + wget https://github.com/mikefarah/yq/releases/download/v4.34.2/yq_linux_amd64 -O /usr/local/bin/yq + chmod +x /usr/local/bin/yq + - name: Get Labels from release-drafter.yml + id: get_labels + run: | + curl -s "https://raw.githubusercontent.com/cBioPortal/cbioportal/master/.github/release-drafter.yml" | \ + yq -r '.categories[].labels[]' > labels.txt + - name: Check Labels + id: check_labels + run: | + PR_NUMBER=$(jq -r ".number" $GITHUB_EVENT_PATH) + PR_LABELS=$(curl -s "https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER" | \ + jq -r '.labels[].name') + mapfile -t AVAILABLE_LABELS < labels.txt + for LABEL in ${PR_LABELS[@]}; do + if [[ "$LABEL" == "skip-changelog" ]]; then + echo "PR contains a valid label: skip-changelog" + exit 0 # Valid label found, exit successfully + fi + for AVAILABLE_LABEL in "${AVAILABLE_LABELS[@]}"; do + if [[ "$AVAILABLE_LABEL" == "$LABEL" ]]; then + echo "PR contains a valid label: $LABEL" + exit 0 # Valid label found, exit successfully + fi + done + done + echo "No valid label found on PR." + echo "Available label options from release-drafter.yml:" + cat labels.txt + exit 1 # No valid label found, exit with an error diff --git a/core/src/main/java/org/mskcc/cbio/portal/dao/DaoCosmicData.java b/core/src/main/java/org/mskcc/cbio/portal/dao/DaoCosmicData.java index b7e0960ad37..24a8209e64b 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/dao/DaoCosmicData.java +++ b/core/src/main/java/org/mskcc/cbio/portal/dao/DaoCosmicData.java @@ -39,7 +39,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -116,7 +115,7 @@ private static Set filterTruncatingCosmicByPosition( Set ret = new HashSet(); Pattern p = Pattern.compile("[0-9]+"); - int mutPos = mut.getOncotatorProteinPosStart(); + int mutPos = mut.getProteinPosStart(); for (CosmicMutationFrequency cmf : cmfs) { String aa = cmf.getAminoAcidChange(); Matcher m = p.matcher(aa); diff --git a/core/src/main/java/org/mskcc/cbio/portal/dao/DaoMutation.java b/core/src/main/java/org/mskcc/cbio/portal/dao/DaoMutation.java index b3296569615..8adbdaddb3f 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/dao/DaoMutation.java +++ b/core/src/main/java/org/mskcc/cbio/portal/dao/DaoMutation.java @@ -145,23 +145,16 @@ public static int addMutationEvent(ExtendedMutation.MutationEvent event) throws event.getTumorSeqAllele(), event.getProteinChange(), event.getMutationType(), - event.getFunctionalImpactScore(), - Float.toString(event.getFisValue()), - event.getLinkXVar(), - event.getLinkPdb(), - event.getLinkMsa(), event.getNcbiBuild(), event.getStrand(), event.getVariantType(), event.getDbSnpRs(), event.getDbSnpValStatus(), - event.getOncotatorDbSnpRs(), - event.getOncotatorRefseqMrnaId(), - event.getOncotatorCodonChange(), - event.getOncotatorUniprotName(), - event.getOncotatorUniprotAccession(), - Integer.toString(event.getOncotatorProteinPosStart()), - Integer.toString(event.getOncotatorProteinPosEnd()), + event.getRefseqMrnaId(), + event.getCodonChange(), + event.getUniprotAccession(), + Integer.toString(event.getProteinPosStart()), + Integer.toString(event.getProteinPosEnd()), boolToStr(event.isCanonicalTranscript()), keyword==null ? "\\N":(event.getGene().getHugoGeneSymbolAllCaps()+" "+keyword)); return 1; @@ -800,24 +793,17 @@ private static ExtendedMutation.MutationEvent extractMutationEvent(ResultSet rs) event.setEndPosition(rs.getLong("END_POSITION")); event.setProteinChange(rs.getString("PROTEIN_CHANGE")); event.setMutationType(rs.getString("MUTATION_TYPE")); - event.setFunctionalImpactScore(rs.getString("FUNCTIONAL_IMPACT_SCORE")); - event.setFisValue(rs.getFloat("FIS_VALUE")); - event.setLinkXVar(rs.getString("LINK_XVAR")); - event.setLinkPdb(rs.getString("LINK_PDB")); - event.setLinkMsa(rs.getString("LINK_MSA")); event.setNcbiBuild(rs.getString("NCBI_BUILD")); event.setStrand(rs.getString("STRAND")); event.setVariantType(rs.getString("VARIANT_TYPE")); event.setDbSnpRs(rs.getString("DB_SNP_RS")); event.setDbSnpValStatus(rs.getString("DB_SNP_VAL_STATUS")); event.setReferenceAllele(rs.getString("REFERENCE_ALLELE")); - event.setOncotatorDbSnpRs(rs.getString("ONCOTATOR_DBSNP_RS")); - event.setOncotatorRefseqMrnaId(rs.getString("ONCOTATOR_REFSEQ_MRNA_ID")); - event.setOncotatorCodonChange(rs.getString("ONCOTATOR_CODON_CHANGE")); - event.setOncotatorUniprotName(rs.getString("ONCOTATOR_UNIPROT_ENTRY_NAME")); - event.setOncotatorUniprotAccession(rs.getString("ONCOTATOR_UNIPROT_ACCESSION")); - event.setOncotatorProteinPosStart(rs.getInt("ONCOTATOR_PROTEIN_POS_START")); - event.setOncotatorProteinPosEnd(rs.getInt("ONCOTATOR_PROTEIN_POS_END")); + event.setRefseqMrnaId(rs.getString("REFSEQ_MRNA_ID")); + event.setCodonChange(rs.getString("CODON_CHANGE")); + event.setUniprotAccession(rs.getString("UNIPROT_ACCESSION")); + event.setProteinPosStart(rs.getInt("PROTEIN_POS_START")); + event.setProteinPosEnd(rs.getInt("PROTEIN_POS_END")); event.setCanonicalTranscript(rs.getBoolean("CANONICAL_TRANSCRIPT")); event.setTumorSeqAllele(rs.getString("TUMOR_SEQ_ALLELE")); event.setKeyword(rs.getString("KEYWORD")); @@ -1391,12 +1377,12 @@ public static Collection> countSamplesWithProteinPosStarts( if (geneIdSet.size() == 0 || internalProfileIds.size() == 0) return new ArrayList>(); //empty IN() clause would be a SQL error below try { con = JdbcUtil.getDbConnection(DaoMutation.class); - String sql = "SELECT ONCOTATOR_PROTEIN_POS_START, GENETIC_PROFILE_ID, mutation.ENTREZ_GENE_ID, count(DISTINCT SAMPLE_ID) " + + String sql = "SELECT PROTEIN_POS_START, GENETIC_PROFILE_ID, mutation.ENTREZ_GENE_ID, count(DISTINCT SAMPLE_ID) " + "FROM mutation INNER JOIN mutation_event ON mutation.MUTATION_EVENT_ID=mutation_event.MUTATION_EVENT_ID " + "WHERE mutation.ENTREZ_GENE_ID IN (" + StringUtils.join(geneIdSet, ",") + ") " + "AND GENETIC_PROFILE_ID IN (" + StringUtils.join(internalProfileIds, ",") + ") " + - "AND (mutation.ENTREZ_GENE_ID, ONCOTATOR_PROTEIN_POS_START) IN (" + StringUtils.join(proteinPosStarts, ",") + ") " + - "GROUP BY ONCOTATOR_PROTEIN_POS_START, GENETIC_PROFILE_ID, mutation.ENTREZ_GENE_ID"; + "AND (mutation.ENTREZ_GENE_ID, PROTEIN_POS_START) IN (" + StringUtils.join(proteinPosStarts, ",") + ") " + + "GROUP BY PROTEIN_POS_START, GENETIC_PROFILE_ID, mutation.ENTREZ_GENE_ID"; pstmt = con.prepareStatement(sql); rs = pstmt.executeQuery(); Collection> data = new ArrayList>(); diff --git a/core/src/main/java/org/mskcc/cbio/portal/dao/JdbcDataSource.java b/core/src/main/java/org/mskcc/cbio/portal/dao/JdbcDataSource.java index 5b9d0548669..00bcb76b7cb 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/dao/JdbcDataSource.java +++ b/core/src/main/java/org/mskcc/cbio/portal/dao/JdbcDataSource.java @@ -3,28 +3,44 @@ import org.apache.commons.dbcp2.BasicDataSource; import org.mskcc.cbio.portal.util.DatabaseProperties; import org.apache.commons.lang3.StringUtils; +import org.springframework.util.Assert; /** * Data source that self-initializes based on cBioPortal configuration. */ public class JdbcDataSource extends BasicDataSource { + public JdbcDataSource () { DatabaseProperties dbProperties = DatabaseProperties.getInstance(); + String host = dbProperties.getDbHost(); String userName = dbProperties.getDbUser(); String password = dbProperties.getDbPassword(); String mysqlDriverClassName = dbProperties.getDbDriverClassName(); String database = dbProperties.getDbName(); - String useSSL = (!StringUtils.isBlank(dbProperties.getDbUseSSL())) ? dbProperties.getDbUseSSL() : "false"; String enablePooling = (!StringUtils.isBlank(dbProperties.getDbEnablePooling())) ? dbProperties.getDbEnablePooling(): "false"; - String url ="jdbc:mysql://" + host + "/" + database + - "?user=" + userName + "&password=" + password + - "&zeroDateTimeBehavior=convertToNull&useSSL=" + useSSL; + String connectionURL = dbProperties.getConnectionURL(); + + Assert.isTrue( + !defined(host) && !defined(database) && !defined(dbProperties.getDbUseSSL()), + "\n----------------------------------------------------------------------------------------------------------------" + + "-- Connection error:\n" + + "-- You try to connect to the database using the deprecated 'db.host', 'db.portal_db_name' and 'db.use_ssl' properties.\n" + + "-- Please remove these properties and use the 'db.connection_string' property instead. See https://docs.cbioportal.org/deployment/customization/portal.properties-reference/\n" + + "-- for assistance on building a valid connection string.\n" + + "----------------------------------------------------------------------------------------------------------------\n" + ); + + Assert.hasText(userName, errorMessage("username", "db.user")); + Assert.hasText(password, errorMessage("password", "db.password")); + Assert.hasText(mysqlDriverClassName, errorMessage("driver class name", "db.driver")); + + this.setUrl(connectionURL); + // Set up poolable data source this.setDriverClassName(mysqlDriverClassName); this.setUsername(userName); this.setPassword(password); - this.setUrl(url); // Disable this to avoid caching statements this.setPoolPreparedStatements(Boolean.valueOf(enablePooling)); // these are the values cbioportal has been using in their production @@ -37,4 +53,12 @@ public JdbcDataSource () { this.setValidationQuery("SELECT 1"); this.setJmxName("org.cbioportal:DataSource=" + database); } + + private String errorMessage(String displayName, String propertyName) { + return String.format("No %s provided for database connection. Please set '%s' in portal.properties.", displayName, propertyName); + } + + private boolean defined(String property) { + return property != null && !property.isEmpty(); + } } diff --git a/core/src/main/java/org/mskcc/cbio/portal/model/ExtendedMutation.java b/core/src/main/java/org/mskcc/cbio/portal/model/ExtendedMutation.java index 59aa4e44309..21c276f225f 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/model/ExtendedMutation.java +++ b/core/src/main/java/org/mskcc/cbio/portal/model/ExtendedMutation.java @@ -44,20 +44,16 @@ */ public final class ExtendedMutation { + public final static class MutationEvent { private long mutationEventId; private CanonicalGene gene; private String chr; - private long startPosition; + private long startPosition; private long endPosition; private String proteinChange; // amino acid change private String mutationType; // variant classification - private String functionalImpactScore; - private float fisValue; - private String linkXVar; - private String linkPdb; - private String linkMsa; - private String keyword; + private String keyword; private String ncbiBuild; private String strand; private String variantType; @@ -65,13 +61,11 @@ public final static class MutationEvent { private String tumorSeqAllele; private String dbSnpRs; private String dbSnpValStatus; - private String oncotatorDbSnpRs; - private String oncotatorRefseqMrnaId; - private String oncotatorUniprotName; - private String oncotatorUniprotAccession; - private String oncotatorCodonChange; - private int oncotatorProteinPosStart; - private int oncotatorProteinPosEnd; + private String refseqMrnaId; + private String uniprotAccession; + private String codonChange; + private int proteinPosStart; + private int proteinPosEnd; private boolean canonicalTranscript; public long getMutationEventId() { @@ -132,46 +126,6 @@ public void setMutationType(String mutationType) { this.mutationType = mutationType; } - public String getFunctionalImpactScore() { - return functionalImpactScore; - } - - public void setFunctionalImpactScore(String functionalImpactScore) { - this.functionalImpactScore = functionalImpactScore; - } - - public float getFisValue() { - return fisValue; - } - - public void setFisValue(float fisValue) { - this.fisValue = fisValue; - } - - public String getLinkXVar() { - return linkXVar; - } - - public void setLinkXVar(String linkXVar) { - this.linkXVar = linkXVar; - } - - public String getLinkPdb() { - return linkPdb; - } - - public void setLinkPdb(String linkPdb) { - this.linkPdb = linkPdb; - } - - public String getLinkMsa() { - return linkMsa; - } - - public void setLinkMsa(String linkMsa) { - this.linkMsa = linkMsa; - } - public String getKeyword() { return keyword; } @@ -236,68 +190,44 @@ public void setDbSnpValStatus(String dbSnpValStatus) { this.dbSnpValStatus = dbSnpValStatus; } - public String getOncotatorDbSnpRs() { - return oncotatorDbSnpRs; - } - - public void setOncotatorDbSnpRs(String oncotatorDbSnpRs) { - this.oncotatorDbSnpRs = oncotatorDbSnpRs; - } - - public String getOncotatorRefseqMrnaId() { - return oncotatorRefseqMrnaId; + public String getRefseqMrnaId() { + return refseqMrnaId; } - public void setOncotatorRefseqMrnaId(String oncotatorRefseqMrnaId) { - this.oncotatorRefseqMrnaId = oncotatorRefseqMrnaId; + public void setRefseqMrnaId(String refseqMrnaId) { + this.refseqMrnaId = refseqMrnaId; } - - public String getOncotatorUniprotName() { - return oncotatorUniprotName; - } - - /** - * Set the UniprotKB name (formerly known as ID) of the protein record. - * - * @param oncotatorUniprotName the UniprotKB name - * @deprecated set the accession with - * {@link #setOncotatorUniprotAccession(String)} instead - */ - @Deprecated - public void setOncotatorUniprotName(String oncotatorUniprotName) { - this.oncotatorUniprotName = oncotatorUniprotName; - } - - public String getOncotatorUniprotAccession() { - return oncotatorUniprotAccession; + + public String getUniprotAccession() { + return uniprotAccession; } - public void setOncotatorUniprotAccession(String oncotatorUniprotAccession) { - this.oncotatorUniprotAccession = oncotatorUniprotAccession; + public void setUniprotAccession(String uniprotAccession) { + this.uniprotAccession = uniprotAccession; } - public String getOncotatorCodonChange() { - return oncotatorCodonChange; + public String getCodonChange() { + return codonChange; } - public void setOncotatorCodonChange(String oncotatorCodonChange) { - this.oncotatorCodonChange = oncotatorCodonChange; + public void setCodonChange(String codonChange) { + this.codonChange = codonChange; } - public int getOncotatorProteinPosStart() { - return oncotatorProteinPosStart; + public int getProteinPosStart() { + return proteinPosStart; } - public void setOncotatorProteinPosStart(int oncotatorProteinPosStart) { - this.oncotatorProteinPosStart = oncotatorProteinPosStart; + public void setProteinPosStart(int proteinPosStart) { + this.proteinPosStart = proteinPosStart; } - public int getOncotatorProteinPosEnd() { - return oncotatorProteinPosEnd; + public int getProteinPosEnd() { + return proteinPosEnd; } - public void setOncotatorProteinPosEnd(int oncotatorProteinPosEnd) { - this.oncotatorProteinPosEnd = oncotatorProteinPosEnd; + public void setProteinPosEnd(int proteinPosEnd) { + this.proteinPosEnd = proteinPosEnd; } public boolean isCanonicalTranscript() { @@ -543,47 +473,7 @@ public void setAminoAcidChange(String aminoAcidChange) { this.aminoAcidChange = aminoAcidChange; } - - public String getFunctionalImpactScore() { - return event.getFunctionalImpactScore(); - } - - public void setFunctionalImpactScore(String fImpact) { - event.setFunctionalImpactScore(fImpact); - } - - public float getFisValue() { - return event.getFisValue(); - } - - public void setFisValue(Float fisValue) { - event.setFisValue(fisValue); - } - - public String getLinkXVar() { - return event.getLinkXVar(); - } - - public void setLinkXVar(String linkXVar) { - event.setLinkXVar(linkXVar); - } - - public String getLinkPdb() { - return event.getLinkPdb(); - } - - public void setLinkPdb(String linkPdb) { - event.setLinkPdb(linkPdb); - } - - public String getLinkMsa() { - return event.getLinkMsa(); - } - - public void setLinkMsa(String linkMsa) { - event.setLinkMsa(linkMsa); - } - + public String getSequencer() { return sequencer; } @@ -820,80 +710,54 @@ public void setNormalRefCount(Integer normalRefCount) { this.normalRefCount = normalRefCount; } - public String getOncotatorDbSnpRs() { - return event.getOncotatorDbSnpRs(); - } - - public void setOncotatorDbSnpRs(String oncotatorDbSnpRs) { - event.setOncotatorDbSnpRs(oncotatorDbSnpRs); - } - - public String getOncotatorRefseqMrnaId() - { - return event.getOncotatorRefseqMrnaId(); - } - - public void setOncotatorRefseqMrnaId(String oncotatorRefseqMrnaId) - { - event.setOncotatorRefseqMrnaId(oncotatorRefseqMrnaId); - } - - public String getOncotatorUniprotName() + public String getRefseqMrnaId() { - return event.getOncotatorUniprotName(); + return event.getRefseqMrnaId(); } - /** - * Set the UniprotKB name (formerly known as ID) of the protein record. - * - * @param oncotatorUniprotName the UniprotKB name - * @deprecated set the accession with - * {@link #setOncotatorUniprotAccession(String)} instead - */ - @Deprecated - public void setOncotatorUniprotName(String oncotatorUniprotName) + public void setRefseqMrnaId(String refseqMrnaId) { - event.setOncotatorUniprotName(oncotatorUniprotName); + event.setRefseqMrnaId(refseqMrnaId); } - public String getOncotatorUniprotAccession() + public String getUniprotAccession() { - return event.getOncotatorUniprotAccession(); + return event.getUniprotAccession(); } - public void setOncotatorUniprotAccession(String oncotatorUniprotAccession) + public void setUniprotAccession(String uniprotAccession) { - event.setOncotatorUniprotAccession(oncotatorUniprotAccession); + event.setUniprotAccession(uniprotAccession); } - public String getOncotatorCodonChange() + public String getCodonChange() { - return event.getOncotatorCodonChange(); + return event.getCodonChange(); } - public void setOncotatorCodonChange(String oncotatorCodonChange) + public void setCodonChange(String codonChange) { - event.setOncotatorCodonChange(oncotatorCodonChange); + event.setCodonChange(codonChange); } - public int getOncotatorProteinPosStart() + public int getProteinPosStart() { - return event.getOncotatorProteinPosStart(); + return event.getProteinPosStart(); } - public void setOncotatorProteinPosStart(int oncotatorProteinPosStart) + public void setProteinPosStart(int proteinPosStart) { - event.setOncotatorProteinPosStart(oncotatorProteinPosStart); + event.setProteinPosStart(proteinPosStart); } - public int getOncotatorProteinPosEnd() + public int getProteinPosEnd() { - return event.getOncotatorProteinPosEnd(); + return event.getProteinPosEnd(); } - public void setOncotatorProteinPosEnd(int oncotatorProteinPosEnd) + public void setProteinPosEnd(int proteinPosEnd) { - event.setOncotatorProteinPosEnd(oncotatorProteinPosEnd); + event.setProteinPosEnd(proteinPosEnd); } public boolean isCanonicalTranscript() diff --git a/core/src/main/java/org/mskcc/cbio/portal/scripts/ImportCosmicData.java b/core/src/main/java/org/mskcc/cbio/portal/scripts/ImportCosmicData.java index 6d2e29fecc9..cea48b84b0d 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/scripts/ImportCosmicData.java +++ b/core/src/main/java/org/mskcc/cbio/portal/scripts/ImportCosmicData.java @@ -61,7 +61,7 @@ public void importData() throws IOException, DaoException { DaoGeneOptimized daoGeneOptimized = DaoGeneOptimized.getInstance(); // Pattern: must have gene, strand, cds, aa and cnt in any order, with other strings possibly in between. Pattern p = Pattern.compile("(?=.*GENE=[^;]+.*)(?=.*STRAND=(.).*)(?=.*CDS=[^;]+.*)(?=.*AA=p\\.[^;]+.*)(?=.*CNT=[0-9]+.*)"); - + Pattern id_pat = Pattern.compile("(?=.*LEGACY_ID=[^;]+.*)"); MySQLbulkLoader.bulkLoadOn(); FileReader reader = new FileReader(file); BufferedReader buf = new BufferedReader(reader); @@ -77,13 +77,27 @@ public void importData() throws IOException, DaoException { } String id = parts[2]; + String infoColumnValue = parts[7]; if (!id.matches("COS(M|V)[0-9]+")) { System.err.println("Wrong cosmic ID: "+id); } else { - id = id.substring(4); + if (id.matches("COSM[0-9]+")) { //COSM can be taken as is + id = id.substring(4); + } else { //COSV does not map correctly, COSM still present in info-column + Matcher id_match = id_pat.matcher(infoColumnValue); + if (!id_match.find()) { + System.err.println("Cannot parse Legacy ID: "+line); + } + String id_items[] = infoColumnValue.split(";"); + for (String s: id_items) { + if (s.startsWith("LEGACY_ID=")) { + id = s.substring(14); + } + } + + } } - - String infoColumnValue = parts[7]; + Matcher m = p.matcher(infoColumnValue); if (m.find()) { Map fieldValues = evaluateFieldValues(infoColumnValue); diff --git a/core/src/main/java/org/mskcc/cbio/portal/scripts/ImportExtendedMutationData.java b/core/src/main/java/org/mskcc/cbio/portal/scripts/ImportExtendedMutationData.java index aec4708cb3b..39dd97c30ef 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/scripts/ImportExtendedMutationData.java +++ b/core/src/main/java/org/mskcc/cbio/portal/scripts/ImportExtendedMutationData.java @@ -206,31 +206,6 @@ public void importData() throws IOException, DaoException { if (record.getEndPosition() < 0) record.setEndPosition(0); - String functionalImpactScore = ""; - // using -1 is not safe, FIS can be a negative value - Float fisValue = Float.MIN_VALUE; - String linkXVar = ""; - String linkMsa = ""; - String linkPdb = ""; - - if (fileHasOMAData) - { -// functionalImpactScore = getField(parts, "MA:FImpact" ); -// fisValue = getField(parts, "MA:FIS"); -// linkXVar = getField(parts, "MA:link.var" ); -// linkMsa = getField(parts, "MA:link.MSA" ); -// linkPdb = getField(parts, "MA:link.PDB" ); - - functionalImpactScore = record.getMaFuncImpact(); - fisValue = record.getMaFIS(); - linkXVar = record.getMaLinkVar(); - linkMsa = record.getMaLinkMsa(); - linkPdb = record.getMaLinkPdb(); - - functionalImpactScore = transformOMAScore(functionalImpactScore); - linkXVar = linkXVar.replace("\"", ""); - } - String mutationType, proteinChange, aaChange, @@ -361,11 +336,6 @@ public void importData() throws IOException, DaoException { mutation.setEndPosition(record.getEndPosition()); mutation.setValidationStatus(record.getValidationStatus()); mutation.setMutationStatus(record.getMutationStatus()); - mutation.setFunctionalImpactScore(functionalImpactScore); - mutation.setFisValue(fisValue); - mutation.setLinkXVar(linkXVar); - mutation.setLinkPdb(linkPdb); - mutation.setLinkMsa(linkMsa); mutation.setNcbiBuild(record.getNcbiBuild()); mutation.setStrand(record.getStrand()); mutation.setVariantType(record.getVariantType()); @@ -397,12 +367,12 @@ public void importData() throws IOException, DaoException { mutation.setNormalAltCount(ExtendedMutationUtil.getNormalAltCount(record)); mutation.setNormalRefCount(ExtendedMutationUtil.getNormalRefCount(record)); - // TODO rename the oncotator column names (remove "oncotator") - mutation.setOncotatorCodonChange(codonChange); - mutation.setOncotatorRefseqMrnaId(refseqMrnaId); - mutation.setOncotatorUniprotAccession(uniprotAccession); - mutation.setOncotatorProteinPosStart(proteinPosStart); - mutation.setOncotatorProteinPosEnd(proteinPosEnd); + // renamed the oncotator column names to mutation + mutation.setCodonChange(codonChange); + mutation.setRefseqMrnaId(refseqMrnaId); + mutation.setUniprotAccession(uniprotAccession); + mutation.setProteinPosStart(proteinPosStart); + mutation.setProteinPosEnd(proteinPosEnd); mutation.setDriverFilter(record.getDriverFilter()); mutation.setDriverFilterAnn(record.getDriverFilterAnn()); diff --git a/core/src/main/java/org/mskcc/cbio/portal/servlet/CalcFisherExactTest.java b/core/src/main/java/org/mskcc/cbio/portal/servlet/CalcFisherExactTest.java index 346c4ecc0ff..16073e48ff0 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/servlet/CalcFisherExactTest.java +++ b/core/src/main/java/org/mskcc/cbio/portal/servlet/CalcFisherExactTest.java @@ -44,13 +44,13 @@ import org.mskcc.cbio.portal.stats.FisherExact; /** - * Calculate the cumulative (one-tail) p-value out of fisher exact test + * Calculate the cumulative (two-tail) p-value out of fisher exact test * * @param a a, b, c, d are the four cells in a 2x2 matrix * @param b * @param c * @param d - * @return one-tailed P-value (right or left, whichever is smallest) + * @return two-tailed P-value (right or left, whichever is smallest) * */ public class CalcFisherExactTest extends HttpServlet { @@ -86,7 +86,7 @@ protected void doPost(HttpServletRequest httpServletRequest, int c = Integer.parseInt(dataSet.split(" ")[2]); int d = Integer.parseInt(dataSet.split(" ")[3]); FisherExact fisher = new FisherExact(a + b + c + d); - double pValue = fisher.getCumlativeP(a, b, c, d); + double pValue = fisher.getTwoTailedP(a, b, c, d); result = result.concat(String.valueOf(pValue) + " "); } } diff --git a/core/src/main/java/org/mskcc/cbio/portal/stats/OddsRatio.java b/core/src/main/java/org/mskcc/cbio/portal/stats/OddsRatio.java index c66b49426a8..92f8f839559 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/stats/OddsRatio.java +++ b/core/src/main/java/org/mskcc/cbio/portal/stats/OddsRatio.java @@ -87,7 +87,7 @@ public OddsRatio(ProfileDataSummary pDataSummary, String geneA, String geneB) { oddsRatio = ((double) (a * d)) / ((double) (b * c)); FisherExact fisher = new FisherExact(a + b + c + d); - pValue = fisher.getCumlativeP(a, b, c, d); + pValue = fisher.getTwoTailedP(a, b, c, d); lowerConfidenceInterval = Math.exp(Math.log(oddsRatio) - 1.96 * (Math.sqrt(1 / (double) a + 1 / (double) b + 1 / (double) c + 1 / (double) d))); upperConfidenceInterval = Math.exp(Math.log(oddsRatio) + 1.96 * (Math.sqrt(1 / (double) a @@ -103,7 +103,7 @@ public double getOddsRatio() { return oddsRatio; } - public double getCumulativeP() { + public double getTwoTailedP() { return pValue; } diff --git a/core/src/main/java/org/mskcc/cbio/portal/util/DatabaseProperties.java b/core/src/main/java/org/mskcc/cbio/portal/util/DatabaseProperties.java index fe19d5b538f..e2ec2753bec 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/util/DatabaseProperties.java +++ b/core/src/main/java/org/mskcc/cbio/portal/util/DatabaseProperties.java @@ -47,6 +47,7 @@ public class DatabaseProperties { private String dbDriverClassName; private String dbUseSSL; private String dbEnablePooling; + private String connectionURL; // No production keys stored in filesystem or code: digest the key; put it in properties; load it into dbms on startup private static DatabaseProperties dbProperties; @@ -63,6 +64,7 @@ public static DatabaseProperties getInstance() { dbProperties.setDbDriverClassName(GlobalProperties.getProperty("db.driver")); dbProperties.setDbUseSSL(GlobalProperties.getProperty("db.use_ssl")); dbProperties.setDbEnablePooling(GlobalProperties.getProperty("db.enable_pooling")); + dbProperties.setConnectionURL(GlobalProperties.getProperty("db.connection_string")); } return dbProperties; } @@ -134,4 +136,12 @@ public void setDbEnablePooling(String dbEnablePooling) { this.dbEnablePooling = dbEnablePooling; } + public String getConnectionURL() { + return connectionURL; + } + + public void setConnectionURL(String connectionURL) { + this.connectionURL = connectionURL; + } + } diff --git a/core/src/main/java/org/mskcc/cbio/portal/util/EnrichmentsAnalysisUtil.java b/core/src/main/java/org/mskcc/cbio/portal/util/EnrichmentsAnalysisUtil.java index d1bf2df5851..c1c4adac537 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/util/EnrichmentsAnalysisUtil.java +++ b/core/src/main/java/org/mskcc/cbio/portal/util/EnrichmentsAnalysisUtil.java @@ -652,7 +652,7 @@ private double runFisherExactTest(HashMap singleGeneCaseValueMa } } FisherExact fisher = new FisherExact(a + b + c + d); - return fisher.getCumlativeP(a, b, c, d); + return fisher.getTwoTailedP(a, b, c, d); } private String getCytoband(int geneticEntityId, String geneticProfileStableId) { diff --git a/core/src/main/java/org/mskcc/cbio/portal/util/ExtendedMutationUtil.java b/core/src/main/java/org/mskcc/cbio/portal/util/ExtendedMutationUtil.java index de4c77af7a7..f4f61b59844 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/util/ExtendedMutationUtil.java +++ b/core/src/main/java/org/mskcc/cbio/portal/util/ExtendedMutationUtil.java @@ -195,7 +195,7 @@ public static boolean isAcceptableMutation(String mutationType) { } public static String getMutationType(MafRecord record) { - String mutationType = record.getOncotatorVariantClassification(); + String mutationType = record.getMafVariantClassification(); if (mutationType == null || mutationType.length() == 0 || @@ -298,11 +298,6 @@ public static ExtendedMutation newMutation() { mutation.setEndPosition(defaultLong); mutation.setValidationStatus(defaultStr); mutation.setMutationStatus(defaultStr); - mutation.setFunctionalImpactScore(defaultStr); - mutation.setFisValue(defaultFloat); - mutation.setLinkXVar(defaultStr); - mutation.setLinkPdb(defaultStr); - mutation.setLinkMsa(defaultStr); mutation.setNcbiBuild(defaultStr); mutation.setStrand(defaultStr); mutation.setVariantType(defaultStr); @@ -326,13 +321,11 @@ public static ExtendedMutation newMutation() { mutation.setTumorRefCount(defaultInt); mutation.setNormalAltCount(defaultInt); mutation.setNormalRefCount(defaultInt); - mutation.setOncotatorDbSnpRs(defaultStr); - mutation.setOncotatorCodonChange(defaultStr); - mutation.setOncotatorRefseqMrnaId(defaultStr); - mutation.setOncotatorUniprotName(defaultStr); - mutation.setOncotatorUniprotAccession(defaultStr); - mutation.setOncotatorProteinPosStart(defaultInt); - mutation.setOncotatorProteinPosEnd(defaultInt); + mutation.setCodonChange(defaultStr); + mutation.setRefseqMrnaId(defaultStr); + mutation.setUniprotAccession(defaultStr); + mutation.setProteinPosStart(defaultInt); + mutation.setProteinPosEnd(defaultInt); mutation.setCanonicalTranscript(true); return mutation; diff --git a/core/src/main/java/org/mskcc/cbio/portal/util/GlobalProperties.java b/core/src/main/java/org/mskcc/cbio/portal/util/GlobalProperties.java index cbb82f88129..18209811460 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/util/GlobalProperties.java +++ b/core/src/main/java/org/mskcc/cbio/portal/util/GlobalProperties.java @@ -50,11 +50,13 @@ import java.util.List; import java.util.Properties; +import org.apache.commons.lang.StringUtils; import org.cbioportal.security.spring.authentication.PortalUserDetails; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.util.ResourceUtils; @@ -120,6 +122,7 @@ public class GlobalProperties { public static final String SKIN_RIGHT_NAV_SHOW_EXAMPLES = "skin.right_nav.show_examples"; public static final String SKIN_RIGHT_NAV_SHOW_TESTIMONIALS = "skin.right_nav.show_testimonials"; public static final String SKIN_RIGHT_NAV_SHOW_WHATS_NEW = "skin.right_nav.show_whats_new"; + public static final String SKIN_RIGHT_NAV_SHOW_WEB_TOURS = "skin.right_nav.show_web_tours"; private static String skinAuthorizationMessage; @Value("${skin.authorization_message:Access to this portal is only available to authorized users.}") public void setSkinAuthorizationMessage(String property) { skinAuthorizationMessage = property; } @@ -180,6 +183,12 @@ public void setOncoprintClinicalTracksConfigJson(String property) { oncoprintClinicalTracksConfigJson = property; } + private static String skinPatientViewCustomSampleTypeColorsJson; + @Value("${skin.patient_view.custom_sample_type_colors_json:}") // default is empty string + public void setSkinPatientViewCustomSampleTypeColorsJson(String property) { + skinPatientViewCustomSampleTypeColorsJson = property; + } + // properties for showing the right logo in the header_bar and default logo public static final String SKIN_RIGHT_LOGO = "skin.right_logo"; @@ -362,6 +371,20 @@ public static String parseUrl(String url) @Value("${frontend.url.runtime:}") public void setFrontendUrlRuntime(String property) { frontendUrlRuntime = property; } + private static String downloadGroup; + @Value("${download_group:}") // default is empty string + public void setDownloadGroup(String property) { downloadGroup = property; } + + public static final String DEFAULT_DAT_METHOD = "none"; + + private static String dataAccessTokenMethod; + @Value("${dat.method:none}") // default is empty string + public void setDataAccessTokenMethod(String property) { dataAccessTokenMethod = property; } + + private static String tokenAccessUserRole; + @Value("${dat.filter_user_role:}") // default is empty string + public void setTokenAccessUserRole(String property) { tokenAccessUserRole = property; } + private static Logger LOG = LoggerFactory.getLogger(GlobalProperties.class); private static ConfigPropertyResolver portalProperties = new ConfigPropertyResolver(); private static Properties mavenProperties = initializeProperties(MAVEN_PROPERTIES_FILE_NAME); @@ -789,6 +812,12 @@ public static boolean showRightNavWhatsNew() return showFlag == null || Boolean.parseBoolean(showFlag); } + public static boolean showRightNavWebTours() + { + String showFlag = portalProperties.getProperty(SKIN_RIGHT_NAV_SHOW_WEB_TOURS); + return showFlag == null || Boolean.parseBoolean(showFlag); + } + public static String getAuthorizationMessage() { return skinAuthorizationMessage; @@ -1234,6 +1263,14 @@ public static String getOncoprintClinicalTracksConfigJson() { } } + public static String getSkinPatientViewCustomSampleTypeColorsJson() { + if (skinPatientViewCustomSampleTypeColorsJson.length() > 0) { + return readFile(skinPatientViewCustomSampleTypeColorsJson); + } else { + return null; + } + } + public static String getQuerySetsOfGenes() { String fileName = portalProperties.getProperty(SETSOFGENES_LOCATION, null); return readFile(fileName); @@ -1262,4 +1299,43 @@ public static String getReferenceGenomeName() { public static String getOncoKbToken() { return portalProperties.getProperty(ONCOKB_TOKEN, null); } + + public static String getDownloadControl() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication != null && + StringUtils.isNotEmpty(downloadGroup) && + authentication.getAuthorities().contains(new SimpleGrantedAuthority(downloadGroup))) { + return "show"; + } else { + String downloadControlOption = getProperty("skin.hide_download_controls"); + /* + skin.hide_download_controls return_value + true hide + false show + data data + null/empty show + */ + switch ((downloadControlOption != null) ? downloadControlOption.trim().toLowerCase() : "false") { + case "true": + return "hide"; + case "data": + return "data"; + case "false": + default: + return "show"; + } + } + } + + public static String getDataAccessTokenMethod() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication != null && + StringUtils.isNotEmpty(tokenAccessUserRole)) { + return authentication.getAuthorities().contains(new SimpleGrantedAuthority(tokenAccessUserRole)) ? dataAccessTokenMethod : DEFAULT_DAT_METHOD; + } else { + return dataAccessTokenMethod; + } + } } diff --git a/core/src/main/java/org/mskcc/cbio/portal/util/MutationKeywordUtils.java b/core/src/main/java/org/mskcc/cbio/portal/util/MutationKeywordUtils.java index 4c7e4acfc54..748136e5e11 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/util/MutationKeywordUtils.java +++ b/core/src/main/java/org/mskcc/cbio/portal/util/MutationKeywordUtils.java @@ -150,7 +150,7 @@ public static String guessOncotatorMutationKeyword(String aminoAcidChange, Strin * @return */ public static String guessCosmicKeyword(String aminoAcidChange) { - if (aminoAcidChange.matches("\\(?[A-Z\\*]?[0-9]+\\)?fs\\*?>?\\??[0-9]*") // frameshift + if (aminoAcidChange.matches("\\(?[A-Z\\*]?[0-9]+[A-Z\\*]?\\)?fs\\*?>?\\??[0-9]*") // frameshift || aminoAcidChange.equals("?fs") // frameshift || aminoAcidChange.matches("[A-Z][0-9]+>?\\*") // non sense || aminoAcidChange.matches("M1>?[A-LN-Z]") // non start @@ -166,7 +166,7 @@ public static String guessCosmicKeyword(String aminoAcidChange) { return "truncating"; } - Pattern p = Pattern.compile("(([A-Z\\*])[0-9]+)>?\\2"); + Pattern p = Pattern.compile("(([A-Z\\*])[0-9]+)>?((\\2)|(=)|(%3D))"); // cosmic encodes = as %3D Matcher m = p.matcher(aminoAcidChange); if (m.matches()) { return m.group(1)+" silent"; @@ -181,11 +181,23 @@ public static String guessCosmicKeyword(String aminoAcidChange) { return m.group(1)+" missense"; } - p = Pattern.compile("[A-Z]?([0-9]+)_[A-Z]?[0-9]+ins(([A-Z]+)|([0-9]+))"); + p = Pattern.compile("[A-Z]?([0-9]+)_[A-Z\\*]?[0-9]+ins(([A-Z]+)|([0-9]+))"); //incl. ins before stop codon m = p.matcher(aminoAcidChange); if (m.matches()) { return m.group(1)+" insertion"; } + + p = Pattern.compile("\\*([0-9]+)[A-Z]?ext\\*(([0-9]+)|(\\?))"); //extension of stop codon + m = p.matcher(aminoAcidChange); + if (m.matches()) { + return m.group(1)+" insertion"; + } + + p = Pattern.compile("[A-Z*]([0-9]+)(_[A-Z*][0-9]+)?dup"); //duplication treated as insertion + m = p.matcher(aminoAcidChange); + if (m.matches()) { + return m.group(1)+" insertion"; + } p = Pattern.compile("[A-Z]?([0-9]+)>[A-Z][A-Z]+"); m = p.matcher(aminoAcidChange); @@ -211,11 +223,11 @@ public static String guessCosmicKeyword(String aminoAcidChange) { return m.group(1) + "-" + m.group(2) + " deletion"; } - p = Pattern.compile("[A-Z]([0-9]+)_[A-Z]([0-9]+)>([A-Z]+)"); // this is actually similar to missense mutation for more than 1 amino acid + p = Pattern.compile("[A-Z]([0-9]+)_[A-Z*]([0-9]+)((>)|(delins))([A-Z*]+)"); // this is actually similar to missense mutation for more than 1 amino acid m = p.matcher(aminoAcidChange); if (m.matches()) { int n1 = Integer.parseInt(m.group(2)) - Integer.parseInt(m.group(1)) + 1; - int n2 = m.group(3).length(); + int n2 = m.group(6).length(); if (n1==n2) { return m.group(1) + "-" + m.group(2) + " missense"; } @@ -226,6 +238,27 @@ public static String guessCosmicKeyword(String aminoAcidChange) { return m.group(1) + " insertion"; } + + p = Pattern.compile("[A-Z*]([0-9]+)delins[A-Z*]+[0-9]*"); //delins with 1 del & >1 ins + m = p.matcher(aminoAcidChange); + if (m.matches()) { + return m.group(1)+" insertion"; + } + + p = Pattern.compile("([A-Z*]+)([0-9]+)delext\\*([0-9]+)"); //delext + m = p.matcher(aminoAcidChange); + if (m.matches()) { + int n1 = m.group(1).length(); // no. of AA deleted + int n2 = Integer.parseInt(m.group(3)); // no. of AA added + int n3 = Integer.parseInt(m.group(2)); // location of AA1 + if (n1==n2) { + return m.group(2) + "-" + Integer.toString(n3 + n2 - 1) + " missense"; + } + + if (n1 < n2) { + return m.group(2) + " insertion"; + } + } return null; } diff --git a/core/src/main/java/org/mskcc/cbio/portal/util/SpringUtil.java b/core/src/main/java/org/mskcc/cbio/portal/util/SpringUtil.java index 15e3dc0e95c..f8e2d57976f 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/util/SpringUtil.java +++ b/core/src/main/java/org/mskcc/cbio/portal/util/SpringUtil.java @@ -38,17 +38,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.context.support.GenericXmlApplicationContext; import org.springframework.stereotype.Component; @Component -public class SpringUtil -{ +public class SpringUtil { private static final Logger log = LoggerFactory.getLogger(SpringUtil.class); private static AccessControl accessControl; - private static ApplicationContext context; - private static GenericXmlApplicationContext applicationContext; + private static ApplicationContext applicationContext; @Autowired public void setAccessControl(AccessControl accessControl) { @@ -56,15 +53,13 @@ public void setAccessControl(AccessControl accessControl) { SpringUtil.accessControl = accessControl; } - public static AccessControl getAccessControl() - { + public static AccessControl getAccessControl() { return accessControl; } - public static synchronized void initDataSource() - { - if (SpringUtil.context == null) { - context = new ClassPathXmlApplicationContext("classpath:applicationContext-persistenceConnections.xml"); + public static synchronized void initDataSource() { + if (SpringUtil.applicationContext == null) { + SpringUtil.applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext-persistenceConnections.xml"); } } @@ -74,7 +69,7 @@ public static synchronized void initDataSource() * @return the Spring Framework application context */ public static ApplicationContext getApplicationContext() { - return context; + return applicationContext; } /** @@ -84,7 +79,7 @@ public static ApplicationContext getApplicationContext() { * @param context */ public static void setApplicationContext(ApplicationContext context) { - SpringUtil.context = context; + SpringUtil.applicationContext = context; } /** @@ -93,8 +88,7 @@ public static void setApplicationContext(ApplicationContext context) { * * @param context */ - public static synchronized void initDataSource(ApplicationContext context) - { - SpringUtil.context = context; + public static synchronized void initDataSource(ApplicationContext context) { + SpringUtil.applicationContext = context; } } diff --git a/core/src/main/java/org/mskcc/cbio/portal/web_api/GetMutationData.java b/core/src/main/java/org/mskcc/cbio/portal/web_api/GetMutationData.java index 17920e6e4af..d0653071f7c 100644 --- a/core/src/main/java/org/mskcc/cbio/portal/web_api/GetMutationData.java +++ b/core/src/main/java/org/mskcc/cbio/portal/web_api/GetMutationData.java @@ -182,10 +182,6 @@ public static String getProfileData(String geneticProfileId, buf.append(mutation.getMutationType()).append(TAB); buf.append(mutation.getValidationStatus()).append(TAB); buf.append(mutation.getProteinChange()).append(TAB); - buf.append(mutation.getFunctionalImpactScore()).append(TAB); - buf.append(mutation.getLinkXVar()).append(TAB); - buf.append(mutation.getLinkPdb()).append(TAB); - buf.append(mutation.getLinkMsa()).append(TAB); buf.append(mutation.getChr()).append(TAB); buf.append(mutation.getStartPosition()).append(TAB); buf.append(mutation.getEndPosition()).append(TAB); diff --git a/core/src/main/scripts/importer/cbioportalImporter.py b/core/src/main/scripts/importer/cbioportalImporter.py index a40e9dc4525..2e0d812a191 100755 --- a/core/src/main/scripts/importer/cbioportalImporter.py +++ b/core/src/main/scripts/importer/cbioportalImporter.py @@ -419,8 +419,7 @@ def usage(): '--command [%s] --study_directory ' '--meta_filename ' '--data_filename ' - '--study_ids ' - '--properties-filename ' % (COMMANDS)), file=OUTPUT_FILE) + '--study_ids ' % (COMMANDS)), file=OUTPUT_FILE) def check_args(command): if command not in COMMANDS: diff --git a/core/src/main/scripts/importer/cbioportal_common.py b/core/src/main/scripts/importer/cbioportal_common.py index 3a6355eb07f..21d8c336f28 100644 --- a/core/src/main/scripts/importer/cbioportal_common.py +++ b/core/src/main/scripts/importer/cbioportal_common.py @@ -11,7 +11,9 @@ import logging.handlers from collections import OrderedDict from subprocess import Popen, PIPE, STDOUT - +from typing import Dict, Optional +import dsnparse +import MySQLdb # ------------------------------------------------------------------------------ # globals @@ -37,6 +39,14 @@ ADD_CASE_LIST_CLASS = "org.mskcc.cbio.portal.scripts.AddCaseList" VERSION_UTIL_CLASS = "org.mskcc.cbio.portal.util.VersionUtil" +PORTAL_PROPERTY_DATABASE_USER = 'db.user' +PORTAL_PROPERTY_DATABASE_PW = 'db.password' +PORTAL_PROPERTY_DATABASE_HOST = 'db.host' +PORTAL_PROPERTY_DATABASE_NAME = 'db.portal_db_name' +PORTAL_PROPERTY_DATABASE_URL = 'db.connection_string' +PORTAL_PROPERTY_DATABASE_USESSL = 'db.use_ssl' +REQUIRED_DATABASE_PROPERTIES = [PORTAL_PROPERTY_DATABASE_USER, PORTAL_PROPERTY_DATABASE_PW, PORTAL_PROPERTY_DATABASE_URL] + # provides a key for data types to metafile specification dict. class MetaFileTypes(object): """how we differentiate between data types.""" @@ -1000,3 +1010,100 @@ def run_java(*args): elif process.returncode != 0: raise RuntimeError('Aborting due to error while executing step.') return ret + + +def properties_error_message(display_name: str, property_name: str) -> str: + return f"No {display_name} provided for database connection. Please set '{property_name}' in portal.properties." + + +class PortalProperties(object): + """ Properties object class, just has fields for db conn """ + + def __init__(self, database_user, database_pw, database_url): + self.database_user = database_user + self.database_pw = database_pw + self.database_url = database_url + + +def get_database_properties(properties_filename: str) -> Optional[PortalProperties]: + + properties = parse_properties_file(properties_filename) + + missing_properties = [] + for required_property in REQUIRED_DATABASE_PROPERTIES: + if required_property not in properties or len(properties[required_property]) == 0: + missing_properties.append(required_property) + if missing_properties: + print( + 'Missing required properties : (%s)' % (', '.join(missing_properties)), + file=ERROR_FILE) + return None + + if properties.get(PORTAL_PROPERTY_DATABASE_HOST) is not None \ + or properties.get(PORTAL_PROPERTY_DATABASE_NAME) is not None \ + or properties.get(PORTAL_PROPERTY_DATABASE_USESSL) is not None: + print(""" + ---------------------------------------------------------------------------------------------------------------- + -- Connection error: + -- You try to connect to the database using the deprecated 'db.host', 'db.portal_db_name' and 'db.use_ssl' properties. + -- Please remove these properties and use the 'db.connection_string' property instead. See https://docs.cbioportal.org/deployment/customization/portal.properties-reference/ + -- for assistance on building a valid connection string. + ------------------------------------------------------------f--------------------------------------------------- + """, file=ERROR_FILE) + return None + + return PortalProperties(properties[PORTAL_PROPERTY_DATABASE_USER], + properties[PORTAL_PROPERTY_DATABASE_PW], + properties[PORTAL_PROPERTY_DATABASE_URL]) + + +def parse_properties_file(properties_filename: str) -> Dict[str, str]: + + if not os.path.exists(properties_filename): + print('properties file %s cannot be found' % properties_filename, file=ERROR_FILE) + sys.exit(2) + + properties = {} + with open(properties_filename, 'r') as properties_file: + for line in properties_file: + line = line.strip() + # skip line if its blank or a comment + if len(line) == 0 or line.startswith('#'): + continue + try: + name, value = line.split('=', maxsplit=1) + except ValueError: + print( + 'Skipping invalid entry in property file: %s' % line, + file=ERROR_FILE) + continue + properties[name] = value.strip() + return properties + + +def get_db_cursor(portal_properties: PortalProperties): + + try: + url_elements = dsnparse.parse(portal_properties.database_url) + connection_kwargs = { + "host": url_elements.host, + "port": url_elements.port if url_elements.port is not None else 3306, + "db": url_elements.paths[0], + "user": portal_properties.database_user, + "passwd": portal_properties.database_pw + } + if url_elements.query["useSSL"] == "true": + connection_kwargs['ssl'] = {"ssl_mode": True} + connection_kwargs['ssl_mode'] = 'REQUIRED' + else: + connection_kwargs['ssl_mode'] = 'DISABLED' + connection = MySQLdb.connect(**connection_kwargs) + except MySQLdb.Error as exception: + print(exception, file=ERROR_FILE) + message = ( + "--> Error connecting to server with URL" + + portal_properties.database_url) + print(message, file=ERROR_FILE) + raise ConnectionError(message) from exception + if connection is not None: + return connection, connection.cursor() diff --git a/core/src/main/scripts/importer/importOncokbDiscreteCNA.py b/core/src/main/scripts/importer/importOncokbDiscreteCNA.py index 2fd7ce31e7e..1e81da6b70f 100644 --- a/core/src/main/scripts/importer/importOncokbDiscreteCNA.py +++ b/core/src/main/scripts/importer/importOncokbDiscreteCNA.py @@ -49,15 +49,15 @@ from . import libImportOncokb from . import validateData -ENTREZ_ID = 'Entrez_Gene_Id' -HUGO_SYMBOL = 'Hugo_Symbol' +FIELD_ENTREZ_ID = 'Entrez_Gene_Id' +FIELD_HUGO_SYMBOL = 'Hugo_Symbol' CNA_TYPE = 'copyNameAlterationType' ALTERATION = 'alteration' SAMPLE_ID = 'sample_id' INTERNAL_ID = 'id' ONCOGENIC = libImportOncokb.ONCOKB_JSON_ONCOGENIC_FIELD -required_cna_columns = [HUGO_SYMBOL] +required_cna_columns = [FIELD_HUGO_SYMBOL] # from: cbioportal-frontend file CopyNumberUtils.ts cna_alteration_types = { @@ -66,6 +66,12 @@ "GAIN": 1, "AMPLIFICATION": 2, } +cna_null_values = [ + '0', + 'NA', + 'nan', + '' +] def main_import(args): @@ -130,7 +136,7 @@ def get_cna_events(cna_file_path, server_url=None, alias_map=None): assert server_url or alias_map, 'At least one of "server_url" or "alias_map" must be specified' header_elements = libImportOncokb.get_first_line_cells(libImportOncokb.open_file(cna_file_path), '\t') header_indexes = {} - for required_column in required_cna_columns + [ENTREZ_ID]: + for required_column in required_cna_columns + [FIELD_ENTREZ_ID]: header_indexes[required_column] = header_elements.index(required_column) sample_ids = [i for j, i in enumerate(header_elements) if j not in header_indexes.values()] sample_indexes = {} @@ -150,7 +156,11 @@ def get_cna_events(cna_file_path, server_url=None, alias_map=None): for sample_id in sample_ids: feature = {} feature[SAMPLE_ID] = sample_id - feature[ALTERATION] = int(line_elements[sample_indexes[sample_id]]) + cna_value = line_elements[sample_indexes[sample_id]] + try: + feature[ALTERATION] = 0 if cna_value in cna_null_values else int(round(float(cna_value))) + except TypeError: + continue # CNA value 0 (no CNA) is skipped if not feature[ALTERATION] in cna_alteration_types.values(): continue @@ -160,7 +170,7 @@ def get_cna_events(cna_file_path, server_url=None, alias_map=None): value = line_elements[index] if value != '': feature[column_name] = value - elif column_name != ENTREZ_ID: + elif column_name != FIELD_ENTREZ_ID: print(Color.RED + "Empty value encounterd in column '" + column_name + "' in row " + str( row_counter) + ". OncoKB annotations cannot be imported. Please fix and rerun." + Color.END, file=sys.stderr) @@ -168,10 +178,10 @@ def get_cna_events(cna_file_path, server_url=None, alias_map=None): sys.exit(1) # resolve gene symbols to Entrez Ids if needed - if ENTREZ_ID in feature and feature[ENTREZ_ID] is not None and feature[ - ENTREZ_ID] != '': - entrez_gene_ids = [feature[ENTREZ_ID]] - elif feature[HUGO_SYMBOL] in portal_instance.hugo_entrez_map: + if FIELD_ENTREZ_ID in feature and feature[FIELD_ENTREZ_ID] is not None and feature[ + FIELD_ENTREZ_ID] != '': + entrez_gene_ids = [feature[FIELD_ENTREZ_ID]] + elif feature[FIELD_HUGO_SYMBOL] in portal_instance.hugo_entrez_map: # in case of failure, try aliases entrez_gene_ids = portal_instance.hugo_entrez_map.get( feature[FIELD_HUGO_SYMBOL], @@ -183,23 +193,23 @@ def get_cna_events(cna_file_path, server_url=None, alias_map=None): logger.error(""" Multiple Entrez gene ids were found for a gene. OncoKB annotations will not be imported for this gene. Please fix and rerun. """, - extra={'symbol': feature[HUGO_SYMBOL]}) - feature[ENTREZ_ID] = None + extra={'symbol': feature[FIELD_HUGO_SYMBOL]}) + feature[FIELD_ENTREZ_ID] = None elif len(entrez_gene_ids) == 0: logger.error(""" Could not find the Entrez gene id for a gene. OncoKB annotations will not be imported for this gene. Please fix and rerun. """, - extra={'symbol': feature[HUGO_SYMBOL]}) - feature[ENTREZ_ID] = None + extra={'symbol': feature[FIELD_HUGO_SYMBOL]}) + feature[FIELD_ENTREZ_ID] = None else: - feature[ENTREZ_ID] = str(entrez_gene_ids[0]) - feature[INTERNAL_ID] = "_".join([feature[ENTREZ_ID], feature[CNA_TYPE]]) + feature[FIELD_ENTREZ_ID] = str(entrez_gene_ids[0]) + feature[INTERNAL_ID] = "_".join([feature[FIELD_ENTREZ_ID], feature[CNA_TYPE]]) features.append(feature) cna_file.close() # FIXME this should not occur, right? # Remove duplicate entrez_gene_id/sample_id occurrences. - non_redundant_features_dict = {x[ENTREZ_ID]+x[SAMPLE_ID]:x for x in features} + non_redundant_features_dict = {x[FIELD_ENTREZ_ID]+x[SAMPLE_ID]:x for x in features} print(" DONE") return non_redundant_features_dict.values(); @@ -220,7 +230,7 @@ def create_request_payload(features): elements = {} for feature in features: elements[feature[INTERNAL_ID]] = '{ "copyNameAlterationType":"%s", "gene":{"entrezGeneId":%s}, "id":"%s", "tumorType":null} ' \ - % (feature[CNA_TYPE], feature[ENTREZ_ID], feature[INTERNAL_ID]) + % (feature[CNA_TYPE], feature[FIELD_ENTREZ_ID], feature[INTERNAL_ID]) # normalize for alteration id since same alteration is represented in multiple samples return list(elements.values()) @@ -249,7 +259,7 @@ def write_annotations_to_file(features, pd_file_name): for feature in features: if ONCOGENIC in feature: oncokb_annotation = feature[ONCOGENIC] - line = feature[SAMPLE_ID] + '\t' + feature[ENTREZ_ID] + libImportOncokb.get_annotation_cells(oncokb_annotation) + line = feature[SAMPLE_ID] + '\t' + feature[FIELD_ENTREZ_ID] + libImportOncokb.get_annotation_cells(oncokb_annotation) new_file.write(line) new_file.close() diff --git a/core/src/main/scripts/importer/importOncokbMutation.py b/core/src/main/scripts/importer/importOncokbMutation.py index 61bd0a1a0d5..1b2cc9b0909 100644 --- a/core/src/main/scripts/importer/importOncokbMutation.py +++ b/core/src/main/scripts/importer/importOncokbMutation.py @@ -54,9 +54,9 @@ FIELD_ENTREZ_ID = 'Entrez_Gene_Id' FIELD_HUGO_SYMBOL = 'Hugo_Symbol' INTERNAL_ID = 'id' -PROTEIN_CHANGE = 'HGVSp_Short' -VARIANT_CLASS = 'Variant_Classification' -PROTEIN_POSITION = 'Protein_position' +FIELD_PROTEIN_CHANGE = 'HGVSp_Short' +FIELD_VARIANT_CLASS = 'Variant_Classification' +FIELD_PROTEIN_POSITION = 'Protein_position' ONCOGENIC = libImportOncokb.ONCOKB_JSON_ONCOGENIC_FIELD ONCOKB_ID = libImportOncokb.ONCOKB_JSON_ID_FIELD ONCOKB_QUERY = libImportOncokb.ONCOKB_JSON_QUERY_FIELD @@ -133,21 +133,21 @@ def get_features(mutation_file_path, server_url=None, alias_map=None): row_counter += 1 if line == '\n' or line.startswith('#') or line.startswith(header_elements[0]): continue # skip comment and header line - line_elements = line.rstrip().split('\t') + line_elements = line.rstrip('\n').split('\t') feature = {} for column_name, index in header_indexes.items(): value = line_elements[index] if value != '': - if column_name == PROTEIN_CHANGE: + if column_name == FIELD_PROTEIN_CHANGE: value = value.replace('p.', '') feature[column_name] = value - elif column_name != FIELD_ENTREZ_ID and column_name != PROTEIN_POSITION and column_name != PROTEIN_CHANGE: + elif column_name != FIELD_ENTREZ_ID and column_name != FIELD_PROTEIN_POSITION and column_name != FIELD_PROTEIN_CHANGE: raise RuntimeError("Empty value encountered in column '" + column_name + "' in row " + str(row_counter) + "." \ "OncoKB annotations cannot be imported. Please fix and rerun.") # skip lines that have empty protein change column - if PROTEIN_CHANGE not in feature: + if FIELD_PROTEIN_CHANGE not in feature: continue # resolve gene symbols to Entrez Ids if needed @@ -176,7 +176,7 @@ def get_features(mutation_file_path, server_url=None, alias_map=None): else: feature[FIELD_ENTREZ_ID] = str(entrez_gene_ids[0]) feature[INTERNAL_ID] = "_".join( - [feature[FIELD_ENTREZ_ID], feature[PROTEIN_CHANGE], feature[VARIANT_CLASS]]) + [feature[FIELD_ENTREZ_ID], feature[FIELD_PROTEIN_CHANGE], feature[FIELD_VARIANT_CLASS]]) row_number_to_feature[row_counter] = feature mutation_file.close() @@ -203,9 +203,9 @@ def create_request_payload(row_number_to_feature): """Translate mutation events into JSON for message body.""" elements = {} for row_number, feature in row_number_to_feature.items(): - protein_position = feature[PROTEIN_POSITION] if PROTEIN_POSITION in feature and feature[ - PROTEIN_POSITION] != 'NA' else None - protein_change = feature[PROTEIN_CHANGE] if PROTEIN_CHANGE in feature and feature[PROTEIN_CHANGE] != 'NA' else None + protein_position = feature[FIELD_PROTEIN_POSITION] if FIELD_PROTEIN_POSITION in feature and feature[ + FIELD_PROTEIN_POSITION] != 'NA' else None + protein_change = feature[FIELD_PROTEIN_CHANGE] if FIELD_PROTEIN_CHANGE in feature and feature[FIELD_PROTEIN_CHANGE] != 'NA' else None proteinStart = libImportOncokb.get_protein_pos_start(protein_position, protein_change) proteinEnd = libImportOncokb.get_protein_pos_end(protein_position, protein_change) if proteinEnd == -1: @@ -213,12 +213,12 @@ def create_request_payload(row_number_to_feature): if proteinStart != -1: elements[feature[ INTERNAL_ID]] = '{ "alteration":"%s", "consequence":"%s", "gene":{"entrezGeneId":%s}, "id":"%s", "proteinStart":%s, "proteinEnd":%s, "tumorType":null} ' \ - % (feature[PROTEIN_CHANGE], feature[VARIANT_CLASS], feature[FIELD_ENTREZ_ID], + % (feature[FIELD_PROTEIN_CHANGE], feature[FIELD_VARIANT_CLASS], feature[FIELD_ENTREZ_ID], feature[INTERNAL_ID], proteinStart, proteinEnd) else: elements[feature[ INTERNAL_ID]] = '{ "alteration":"%s", "consequence":"%s", "gene":{"entrezGeneId":%s}, "id":"%s", "tumorType":null} ' \ - % (feature[PROTEIN_CHANGE], feature[VARIANT_CLASS], feature[FIELD_ENTREZ_ID], + % (feature[FIELD_PROTEIN_CHANGE], feature[FIELD_VARIANT_CLASS], feature[FIELD_ENTREZ_ID], feature[INTERNAL_ID]) # normalize for alteration id since same alteration is represented in multiple samples diff --git a/core/src/main/scripts/importer/libImportOncokb.py b/core/src/main/scripts/importer/libImportOncokb.py index 87163da86b7..97a2c506913 100644 --- a/core/src/main/scripts/importer/libImportOncokb.py +++ b/core/src/main/scripts/importer/libImportOncokb.py @@ -279,6 +279,8 @@ def interface(): 'http://localhost:8080') parser.add_argument('-m', '--study_directory', type=str, required=True, help='path to study directory.') + parser.add_argument('-p', '--portal-info-dir', help='Specify a directory of database export JSON files for validation.' + 'genes.json is used to resolved gene symbols/IDs') parser = parser.parse_args() return parser diff --git a/core/src/main/scripts/importer/updateOncokbAnnotations.py b/core/src/main/scripts/importer/updateOncokbAnnotations.py index 780d2ff2ea7..df7799387ca 100644 --- a/core/src/main/scripts/importer/updateOncokbAnnotations.py +++ b/core/src/main/scripts/importer/updateOncokbAnnotations.py @@ -29,11 +29,12 @@ import argparse import importlib import logging.handlers -import os -import requests import sys import MySQLdb from pathlib import Path +from cbioportal_common import get_database_properties, get_db_cursor +import libImportOncokb + # configure relative imports if running as a script; see PEP 366 # it might passed as empty string by certain tooling to mark a top level module @@ -47,16 +48,8 @@ # doesn't include https://github.com/python/cpython/pull/2639 importlib.import_module(__package__) -from . import cbioportal_common -from . import libImportOncokb -from . import validateData ERROR_FILE = sys.stderr -DATABASE_HOST = 'db.host' -DATABASE_NAME = 'db.portal_db_name' -DATABASE_USER = 'db.user' -DATABASE_PW = 'db.password' -REQUIRED_PROPERTIES = [DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PW] REFERENCE_GENOME = {'hg19': 'GRCh37', 'hg38': 'GRCh38'} # from: cbioportal-frontend file CopyNumberUtils.ts @@ -67,84 +60,6 @@ "AMPLIFICATION": 2, } -class PortalProperties(object): - """ Properties object class, just has fields for db conn """ - - def __init__(self, database_host, database_name, database_user, database_pw): - # default port: - self.database_port = 3306 - # if there is a port added to the host name, split and use this one: - if ':' in database_host: - host_and_port = database_host.split(':') - self.database_host = host_and_port[0] - if self.database_host.strip() == 'localhost': - print( - "Invalid host config '" + database_host + "' in properties file. If you want to specify a port on local host use '127.0.0.1' instead of 'localhost'", - file=ERROR_FILE) - sys.exit(1) - self.database_port = int(host_and_port[1]) - else: - self.database_host = database_host - self.database_name = database_name - self.database_user = database_user - self.database_pw = database_pw - -def get_portal_properties(properties_filename): - """ Returns a properties object """ - properties = {} - with open(properties_filename, 'r') as properties_file: - for line in properties_file: - line = line.strip() - # skip line if its blank or a comment - if len(line) == 0 or line.startswith('#'): - continue - try: - name, value = line.split('=', maxsplit=1) - except ValueError: - print( - 'Skipping invalid entry in property file: %s' % (line), - file=ERROR_FILE) - continue - properties[name] = value.strip() - missing_properties = [] - for required_property in REQUIRED_PROPERTIES: - if required_property not in properties or len(properties[required_property]) == 0: - missing_properties.append(required_property) - if missing_properties: - print( - 'Missing required properties : (%s)' % (', '.join(missing_properties)), - file=ERROR_FILE) - return None - # return an instance of PortalProperties - return PortalProperties(properties[DATABASE_HOST], - properties[DATABASE_NAME], - properties[DATABASE_USER], - properties[DATABASE_PW]) - -def get_db_cursor(portal_properties): - """ Establishes a MySQL connection """ - try: - connection = MySQLdb.connect(host=portal_properties.database_host, - port = portal_properties.database_port, - user = portal_properties.database_user, - passwd = portal_properties.database_pw, - db = portal_properties.database_name) - connection.autocommit = False - except MySQLdb.Error as exception: - print(exception, file=ERROR_FILE) - port_info = '' - if portal_properties.database_host.strip() != 'localhost': - # only add port info if host is != localhost (since with localhost apparently sockets are used and not the given port) TODO - perhaps this applies for all names vs ips? - port_info = " on port " + str(portal_properties.database_port) - message = ( - "--> Error connecting to server " - + portal_properties.database_host - + port_info) - print(message, file=ERROR_FILE) - raise ConnectionError(message) from exception - if connection is not None: - return connection, connection.cursor() - def get_current_mutation_data(study_id, cursor): """ Get mutation data from the current study. Returns an array of dictionaries, with the following keys: @@ -307,41 +222,36 @@ def update_annotations(result, connection, cursor, study_id): except MySQLdb.Error as msg: print(msg, file=ERROR_FILE) -def main_import(study_id, properties_filename): - # check existence of properties file - if not os.path.exists(properties_filename): - print('properties file %s cannot be found' % (properties_filename), file=ERROR_FILE) - sys.exit(2) - - # parse properties file - portal_properties = get_portal_properties(properties_filename) +def main_import(study_id, properties_filename): + + portal_properties = get_database_properties(properties_filename) if portal_properties is None: - print('failure reading properties file (%s)' % (properties_filename), file=ERROR_FILE) + print('failure reading properties file (%s)' % properties_filename, file=ERROR_FILE) sys.exit(1) - # Connect to the database + # Connect to the database. # TODO: must be a unique transaction connection, cursor = get_db_cursor(portal_properties) if cursor is None: print('failure connecting to sql database', file=ERROR_FILE) sys.exit(1) - #Query DB to get mutation, cna and structural variant data of the study + # Query DB to get mutation, cna and structural variant data of the study. mutation_study_data = get_current_mutation_data(study_id, cursor) cna_study_data = get_current_cna_data(study_id, cursor) sv_study_data = get_current_sv_data(study_id, cursor) - #Call oncokb to get annotations for the mutation, cna and structural variant data retrieved + # Call OncoKB to get annotations for the mutation, cna and structural variant data retrieved. ref_genome = get_reference_genome(study_id, cursor) mutation_result = fetch_oncokb_mutation_annotations(mutation_study_data, ref_genome) cna_result = fetch_oncokb_copy_number_annotations(cna_study_data, ref_genome) sv_result = fetch_oncokb_sv_annotations(sv_study_data, ref_genome) all_results = mutation_result + cna_result + sv_result - #Query DB to update alteration_driver_annotation table data, one record at a time + # Query DB to update alteration_driver_annotation table data, one record at a time. update_annotations(all_results, connection, cursor, study_id) - #Commit changes to the database at once to ensure a unique transaction + # Commit changes to the database at once to ensure a unique transaction. try: connection.commit() print('Update complete') diff --git a/core/src/main/scripts/importer/validateData.py b/core/src/main/scripts/importer/validateData.py index 5e366cf0bf6..e6cf2c63f7b 100755 --- a/core/src/main/scripts/importer/validateData.py +++ b/core/src/main/scripts/importer/validateData.py @@ -1928,7 +1928,7 @@ def checkAlleleMAFFormat(self, data): if variant_type == "SNP": # Expect alleles to have length 2 when variant type is SNP - if not (len(ref_allele) == 1 and len(tumor_seq_allele1) == 1 and len(tumor_seq_allele1) == 1): + if not (len(ref_allele) == 1 and len(tumor_seq_allele1) == 1 and len(tumor_seq_allele2) == 1): log_message = "Variant_Type indicates a SNP, but length of Reference_Allele, Tumor_Seq_Allele1 " \ "and/or Tumor_Seq_Allele2 do not equal 1." extra_dict = {'line_number': self.line_number, @@ -1936,7 +1936,7 @@ def checkAlleleMAFFormat(self, data): self.send_log_message(self.strict_maf_checks, log_message, extra_dict) if variant_type == "DNP": # Expect alleles to have length 2 when variant type is DNP - if not (len(ref_allele) == 2 and len(tumor_seq_allele1) == 2 and len(tumor_seq_allele1) == 2): + if not (len(ref_allele) == 2 and len(tumor_seq_allele1) == 2 and len(tumor_seq_allele2) == 2): log_message = "Variant_Type indicates a DNP, but length of Reference_Allele, Tumor_Seq_Allele1 " \ "and/or Tumor_Seq_Allele2 do not equal 2." extra_dict = {'line_number': self.line_number, @@ -1944,7 +1944,7 @@ def checkAlleleMAFFormat(self, data): self.send_log_message(self.strict_maf_checks, log_message, extra_dict) if variant_type == "TNP": # Expect alleles to have length 3 when variant type is TNP - if not (len(ref_allele) == 3 and len(tumor_seq_allele1) == 3 and len(tumor_seq_allele1) == 3): + if not (len(ref_allele) == 3 and len(tumor_seq_allele1) == 3 and len(tumor_seq_allele2) == 3): log_message = "Variant_Type indicates a TNP, but length of Reference_Allele, Tumor_Seq_Allele1 " \ "and/or Tumor_Seq_Allele2 do not equal 3." extra_dict = {'line_number': self.line_number, @@ -2600,12 +2600,12 @@ def processTopLines(self, line_list): invalid_values = True elif self.METADATA_LINES[line_index] == 'priority': try: - if int(value) < 0: + if int(value) < -1: raise ValueError() except ValueError: self.logger.error( 'Priority definition should be an integer, and should be ' - 'greater than or equal to zero', + 'greater than or equal to -1', extra={'line_number': line_index + 1, 'column_number': col_index + 1, 'cause': value}) @@ -2941,7 +2941,6 @@ def checkLine(self, data): self.logger.error( 'Value in DFS_STATUS column is not 0:DiseaseFree, ' '1:Recurred/Progressed, 1:Recurred, 1:Progressed', - 'DiseaseFree, Recurred/Progressed, Recurred or Progressed', extra={'line_number': self.line_number, 'column_number': col_index + 1, 'cause': value}) @@ -3271,12 +3270,12 @@ def checkSVstatus(sv_status): 'No Entrez gene id or gene symbol provided for site 1 and site 2', extra={'line_number': self.line_number}) elif site1_gene is None and site2_gene is not None: - self.logger.warning( + self.logger.info( 'No Entrez gene id or gene symbol provided for site 1. ' 'Assuming either the intragenic, deletion, duplication, translocation or inversion variant', extra={'line_number': self.line_number}) elif site2_gene is None and site1_gene is not None: - self.logger.warning( + self.logger.info( 'No Entrez gene id or gene symbol provided for site 2. ' 'Assuming either the intragenic, deletion, duplication, translocation or inversion variant', extra={'line_number': self.line_number}) diff --git a/core/src/main/scripts/migrate_db.py b/core/src/main/scripts/migrate_db.py index 1b2ebb38b79..6ae0463d249 100755 --- a/core/src/main/scripts/migrate_db.py +++ b/core/src/main/scripts/migrate_db.py @@ -6,19 +6,17 @@ import contextlib import argparse from collections import OrderedDict + +from importer.cbioportal_common import get_database_properties, get_db_cursor + import MySQLdb +from pathlib import Path # globals ERROR_FILE = sys.stderr OUTPUT_FILE = sys.stdout -DATABASE_HOST = 'db.host' -DATABASE_NAME = 'db.portal_db_name' -DATABASE_USER = 'db.user' -DATABASE_PW = 'db.password' -DATABASE_USE_SSL = 'db.use_ssl' VERSION_TABLE = 'info' VERSION_FIELD = 'DB_SCHEMA_VERSION' -REQUIRED_PROPERTIES = [DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PW, DATABASE_USE_SSL] ALLOWABLE_GENOME_REFERENCES = ['37', 'hg19', 'GRCh37', '38', 'hg38', 'GRCh38', 'mm10', 'GRCm38'] DEFAULT_GENOME_REFERENCE = 'hg19' MULTI_REFERENCE_GENOME_SUPPORT_MIGRATION_STEP = (2, 11, 0) @@ -26,89 +24,15 @@ SAMPLE_FK_MIGRATION_STEP = (2, 12, 9) FUSIONS_VERBOTEN_STEP = (2, 12, 14) + class PortalProperties(object): """ Properties object class, just has fields for db conn """ - def __init__(self, database_host, database_name, database_user, database_pw, database_use_ssl): - # default port: - self.database_port = 3306 - # if there is a port added to the host name, split and use this one: - if ':' in database_host: - host_and_port = database_host.split(':') - self.database_host = host_and_port[0] - if self.database_host.strip() == 'localhost': - print( - "Invalid host config '" + database_host + "' in properties file. If you want to specify a port on local host use '127.0.0.1' instead of 'localhost'", - file=ERROR_FILE) - sys.exit(1) - self.database_port = int(host_and_port[1]) - else: - self.database_host = database_host - self.database_name = database_name + def __init__(self, database_user, database_pw, database_url): self.database_user = database_user self.database_pw = database_pw - self.database_use_ssl = database_use_ssl + self.database_url = database_url -def get_db_cursor(portal_properties): - """ Establishes a MySQL connection """ - try: - connection_kwargs = {} - connection_kwargs['host'] = portal_properties.database_host - connection_kwargs['port'] = portal_properties.database_port - connection_kwargs['user'] = portal_properties.database_user - connection_kwargs['passwd'] = portal_properties.database_pw - connection_kwargs['db'] = portal_properties.database_name - if portal_properties.database_use_ssl == 'true': - connection_kwargs['ssl'] = {"ssl_mode": True} - - connection = MySQLdb.connect(**connection_kwargs) - except MySQLdb.Error as exception: - print(exception, file=ERROR_FILE) - port_info = '' - if portal_properties.database_host.strip() != 'localhost': - # only add port info if host is != localhost (since with localhost apparently sockets are used and not the given port) TODO - perhaps this applies for all names vs ips? - port_info = " on port " + str(portal_properties.database_port) - message = ( - "--> Error connecting to server " - + portal_properties.database_host - + port_info) - print(message, file=ERROR_FILE) - raise ConnectionError(message) from exception - if connection is not None: - return connection, connection.cursor() - -def get_portal_properties(properties_filename): - """ Returns a properties object """ - properties = {} - with open(properties_filename, 'r') as properties_file: - for line in properties_file: - line = line.strip() - # skip line if its blank or a comment - if len(line) == 0 or line.startswith('#'): - continue - try: - name, value = line.split('=', maxsplit=1) - except ValueError: - print( - 'Skipping invalid entry in property file: %s' % (line), - file=ERROR_FILE) - continue - properties[name] = value.strip() - missing_properties = [] - for required_property in REQUIRED_PROPERTIES: - if required_property not in properties or len(properties[required_property]) == 0: - missing_properties.append(required_property) - if missing_properties: - print( - 'Missing required properties : (%s)' % (', '.join(missing_properties)), - file=ERROR_FILE) - return None - # return an instance of PortalProperties - return PortalProperties(properties[DATABASE_HOST], - properties[DATABASE_NAME], - properties[DATABASE_USER], - properties[DATABASE_PW], - properties[DATABASE_USE_SSL]) def get_db_version(cursor): """ gets the version number of the database """ @@ -134,6 +58,7 @@ def get_db_version(cursor): return None return version + def is_version_larger(version1, version2): """ Checks if version 1 is larger than version 2 """ if version1[0] > version2[0]: @@ -148,17 +73,21 @@ def is_version_larger(version1, version2): return True return False + def is_version_equal(version1, version2): """ Checks if version 1 is equal to version 2""" return version1[0] == version2[0] and version1[1] == version2[1] and version1[2] == version2[2] + def print_all_check_reference_genome_warnings(warnings, force_migration): """ Format warnings for output according to mode, and print to ERROR_FILE """ - space = ' ' + space = ' ' indent = 28 * space allowable_reference_genome_string = ','.join(ALLOWABLE_GENOME_REFERENCES) - clean_up_string = ' Please clean up the mutation_event table and ensure it only contains references to one of the valid reference genomes (%s).' % (allowable_reference_genome_string) - use_default_string = 'the default reference genome (%s) will be used in place of invalid reference genomes and the first encountered reference genome will be used.' % (DEFAULT_GENOME_REFERENCE) + clean_up_string = ' Please clean up the mutation_event table and ensure it only contains references to one of the valid reference genomes (%s).' % ( + allowable_reference_genome_string) + use_default_string = 'the default reference genome (%s) will be used in place of invalid reference genomes and the first encountered reference genome will be used.' % ( + DEFAULT_GENOME_REFERENCE) use_force_string = 'OR use the "--force" option to override this warning, then %s' % (use_default_string) forcing_string = '--force option in effect : %s' % (use_default_string) for warning in warnings: @@ -167,17 +96,21 @@ def print_all_check_reference_genome_warnings(warnings, force_migration): else: print('%s%s%s\n%s%s\n' % (indent, warning, clean_up_string, indent, use_force_string), file=ERROR_FILE) + def validate_reference_genome_values_for_study(warnings, ncbi_to_count, study): """ check if there are unrecognized or varied ncbi_build values for the study, add to warnings if problems are found """ if len(ncbi_to_count) == 1: - for retrieved_ncbi_build in ncbi_to_count: # single iteration + for retrieved_ncbi_build in ncbi_to_count: # single iteration if retrieved_ncbi_build.upper() not in [x.upper() for x in ALLOWABLE_GENOME_REFERENCES]: - msg = 'WARNING: Study %s contains mutation_event records with unsupported NCBI_BUILD value %s.'%(study, retrieved_ncbi_build) + msg = 'WARNING: Study %s contains mutation_event records with unsupported NCBI_BUILD value %s.' % ( + study, retrieved_ncbi_build) warnings.append(msg) elif len(ncbi_to_count) > 1: - msg = 'WARNING: Study %s contains mutation_event records with %s NCBI_BUILD values {ncbi_build:record_count,...} %s.'%(study, len(ncbi_to_count), ncbi_to_count) + msg = 'WARNING: Study %s contains mutation_event records with %s NCBI_BUILD values {ncbi_build:record_count,...} %s.' % ( + study, len(ncbi_to_count), ncbi_to_count) warnings.append(msg) + def check_reference_genome(portal_properties, cursor, force_migration): """ query database for ncbi_build values, aggregate per study, then validate and report problems """ print('Checking database contents for reference genome information', file=OUTPUT_FILE) @@ -193,13 +126,13 @@ def check_reference_genome(portal_properties, cursor, force_migration): group by CANCER_STUDY_IDENTIFIER, NCBI_BUILD """ cursor.execute(sql_statement) - study_to_ncbi_to_count = {} # {cancer_study_identifier : {ncbi_build : record_count}} + study_to_ncbi_to_count = {} # {cancer_study_identifier : {ncbi_build : record_count}} for row in cursor.fetchall(): retrieved_ncbi_build, ref_count, study = row if study in study_to_ncbi_to_count: study_to_ncbi_to_count[study][retrieved_ncbi_build] = ref_count else: - study_to_ncbi_to_count[study] = {retrieved_ncbi_build : ref_count} + study_to_ncbi_to_count[study] = {retrieved_ncbi_build: ref_count} for study in study_to_ncbi_to_count: validate_reference_genome_values_for_study(warnings, study_to_ncbi_to_count[study], study) except MySQLdb.Error as msg: @@ -210,6 +143,7 @@ def check_reference_genome(portal_properties, cursor, force_migration): if not force_migration: sys.exit(1) + def check_and_exit_if_fusions(cursor): try: cursor.execute( @@ -220,7 +154,9 @@ def check_and_exit_if_fusions(cursor): """) fusion_count = cursor.fetchone() if (fusion_count[0] >= 1): - print('Found %i records in the mutation_event table where the mutation_type was "Fusion". The latest database schema does not allow records in the mutation table where mutation_type is set to "Fusion". Studies linked to existing records of this type should be deleted in order to migrate to DB version 2.12.14' % (fusion_count), file=ERROR_FILE) + print( + 'Found %i records in the mutation_event table where the mutation_type was "Fusion". The latest database schema does not allow records in the mutation table where mutation_type is set to "Fusion". Studies linked to existing records of this type should be deleted in order to migrate to DB version 2.12.14' % ( + fusion_count), file=ERROR_FILE) # get the list of studies that need to be cleaned up cursor.execute( """ @@ -240,11 +176,12 @@ def check_and_exit_if_fusions(cursor): for row in rows: print("\t%s" % (row[0]), file=ERROR_FILE) sys.exit(1) - + except MySQLdb.Error as msg: print(msg, file=ERROR_FILE) sys.exit(1) + # TODO: remove this after we update mysql version def check_and_remove_invalid_foreign_keys(cursor): try: @@ -280,6 +217,7 @@ def check_and_remove_invalid_foreign_keys(cursor): print(msg, file=ERROR_FILE) sys.exit(1) + def check_and_remove_type_of_cancer_id_foreign_key(cursor): """The TYPE_OF_CANCER_ID foreign key in the sample table can be either sample_ibfk_1 or sample_ibfk_2. Figure out which one it is and remove it""" try: @@ -295,7 +233,9 @@ def check_and_remove_type_of_cancer_id_foreign_key(cursor): """) rows = cursor.fetchall() if (len(rows) >= 1): - print('sample_ibfk_1 is the foreign key in table sample for type_of_cancer_id column in table type_of_cancer.', file=OUTPUT_FILE) + print( + 'sample_ibfk_1 is the foreign key in table sample for type_of_cancer_id column in table type_of_cancer.', + file=OUTPUT_FILE) cursor.execute( """ ALTER TABLE `sample` DROP FOREIGN KEY sample_ibfk_1; @@ -313,20 +253,24 @@ def check_and_remove_type_of_cancer_id_foreign_key(cursor): """) rows = cursor.fetchall() if (len(rows) >= 1): - print('sample_ibfk_2 is the foreign key in table sample for type_of_cancer_id column in table type_of_cancer.', file=OUTPUT_FILE) + print( + 'sample_ibfk_2 is the foreign key in table sample for type_of_cancer_id column in table type_of_cancer.', + file=OUTPUT_FILE) cursor.execute( """ ALTER TABLE `sample` DROP FOREIGN KEY sample_ibfk_2; """) - print('sample_ibfk_2 foreign key has been deleted.', file=OUTPUT_FILE) + print('sample_ibfk_2 foreign key has been deleted.', file=OUTPUT_FILE) except MySQLdb.Error as msg: print(msg, file=ERROR_FILE) sys.exit(1) + def strip_trailing_comment_from_line(line): - line_parts = re.split("--\s",line) + line_parts = re.split("--\s", line) return line_parts[0] + def run_migration(db_version, sql_filename, connection, cursor, no_transaction, stop_at_version=None): """ Goes through the sql and runs lines based on the version numbers. SQL version should be stated as follows: @@ -376,6 +320,7 @@ def run_migration(db_version, sql_filename, connection, cursor, no_transaction, else: print('Everything up to date, nothing to migrate.', file=OUTPUT_FILE) + def run_statements(statements, connection, cursor, no_transaction): try: if no_transaction: @@ -400,10 +345,12 @@ def run_statements(statements, connection, cursor, no_transaction): sys.exit(1) connection.commit() + def warn_user(): """Warn the user to back up their database before the script runs.""" response = input( - 'WARNING: This script will alter your database! Be sure to back up your data before running.\nContinue running DB migration? (y/n) ' + 'WARNING: This script will alter your database! Be sure to back up your data before running.\n' + 'Continue running DB migration? (y/n) ' ).strip() while response.lower() != 'y' and response.lower() != 'n': response = input( @@ -412,19 +359,23 @@ def warn_user(): if response.lower() == 'n': sys.exit() + def usage(): print( 'migrate_db.py --properties-file [portal properties file] --sql [sql migration file]', file=OUTPUT_FILE) + def main(): """ main function to run mysql migration """ parser = argparse.ArgumentParser(description='cBioPortal DB migration script') parser.add_argument('-y', '--suppress_confirmation', default=False, action='store_true') - parser.add_argument('-p', '--properties-file', type=str, required=True, - help='Path to portal.properties file') - parser.add_argument('-s', '--sql', type=str, required=True, - help='Path to official migration.sql script.') + parser.add_argument('-p', '--properties-file', type=str, required=False, + help='Path to portal.properties file (default: locate it ' + 'relative to the script)') + parser.add_argument('-s', '--sql', type=str, required=False, + help='Path to official migration.sql script. (default: locate it ' + 'relative to the script)') parser.add_argument('-f', '--force', default=False, action='store_true', help='Force to run database migration') parser.add_argument('--no-transaction', default=False, action='store_true', help=""" Do not run migration in a single transaction. Only use this when you known what you are doing!!! @@ -432,22 +383,32 @@ def main(): parser = parser.parse_args() properties_filename = parser.properties_file + if properties_filename is None: + # get the directory name of the currently running script, + # resolving any symlinks + script_dir = Path(__file__).resolve().parent + # go up from cbioportal/core/src/main/scripts/ to cbioportal/ + src_root = script_dir.parent.parent.parent.parent + properties_filename = src_root / 'portal.properties' + sql_filename = parser.sql + if sql_filename is None: + # get the directory name of the currently running script, + # resolving any symlinks + script_dir = Path(__file__).resolve().parent + # go up from cbioportal/core/src/main/scripts/ to cbioportal/ + src_root = script_dir.parent.parent.parent.parent + sql_filename = src_root / 'db-scripts/src/main/resources/migration.sql' - # check existence of properties file and sql file - if not os.path.exists(properties_filename): - print('properties file %s cannot be found' % (properties_filename), file=ERROR_FILE) - usage() - sys.exit(2) if not os.path.exists(sql_filename): print('sql file %s cannot be found' % (sql_filename), file=ERROR_FILE) usage() sys.exit(2) # parse properties file - portal_properties = get_portal_properties(properties_filename) + portal_properties = get_database_properties(properties_filename) if portal_properties is None: - print('failure reading properties file (%s)' % (properties_filename), file=ERROR_FILE) + print('failure reading properties file (%s)' % properties_filename, file=ERROR_FILE) sys.exit(1) # warn user @@ -464,16 +425,19 @@ def main(): with contextlib.closing(connection): db_version = get_db_version(cursor) if is_version_larger(MULTI_REFERENCE_GENOME_SUPPORT_MIGRATION_STEP, db_version): - run_migration(db_version, sql_filename, connection, cursor, parser.no_transaction, stop_at_version=MULTI_REFERENCE_GENOME_SUPPORT_MIGRATION_STEP) - #retrieve reference genomes from database + run_migration(db_version, sql_filename, connection, cursor, parser.no_transaction, + stop_at_version=MULTI_REFERENCE_GENOME_SUPPORT_MIGRATION_STEP) + # retrieve reference genomes from database check_reference_genome(portal_properties, cursor, parser.force) db_version = get_db_version(cursor) if is_version_larger(SAMPLE_FK_MIGRATION_STEP, db_version): - run_migration(db_version, sql_filename, connection, cursor, parser.no_transaction, stop_at_version=SAMPLE_FK_MIGRATION_STEP) + run_migration(db_version, sql_filename, connection, cursor, parser.no_transaction, + stop_at_version=SAMPLE_FK_MIGRATION_STEP) check_and_remove_type_of_cancer_id_foreign_key(cursor) db_version = get_db_version(cursor) if is_version_larger(FUSIONS_VERBOTEN_STEP, db_version): - run_migration(db_version, sql_filename, connection, cursor, parser.no_transaction, stop_at_version=FUSIONS_VERBOTEN_STEP) + run_migration(db_version, sql_filename, connection, cursor, parser.no_transaction, + stop_at_version=FUSIONS_VERBOTEN_STEP) check_and_exit_if_fusions(cursor) db_version = get_db_version(cursor) run_migration(db_version, sql_filename, connection, cursor, parser.no_transaction) @@ -483,6 +447,7 @@ def main(): check_and_remove_invalid_foreign_keys(cursor) print('Finished.', file=OUTPUT_FILE) + # do main if __name__ == '__main__': main() diff --git a/core/src/test/java/org/mskcc/cbio/portal/dao/TestDaoMutation.java b/core/src/test/java/org/mskcc/cbio/portal/dao/TestDaoMutation.java index 4072ecbe144..d55b2085cd1 100644 --- a/core/src/test/java/org/mskcc/cbio/portal/dao/TestDaoMutation.java +++ b/core/src/test/java/org/mskcc/cbio/portal/dao/TestDaoMutation.java @@ -101,11 +101,6 @@ private void runTheTest() throws DaoException{ mutation.setSequencingCenter("Broad"); mutation.setSequencer("SOLiD"); mutation.setProteinChange("BRCA1_123"); - mutation.setFunctionalImpactScore("H"); - mutation.setFisValue(Float.MIN_VALUE); - mutation.setLinkXVar("link1"); - mutation.setLinkPdb("link2"); - mutation.setLinkMsa("link3"); mutation.setNcbiBuild("37/hg19"); mutation.setStrand("+"); mutation.setVariantType("Consolidated"); @@ -132,13 +127,11 @@ private void runTheTest() throws DaoException{ mutation.setTumorRefCount(16); mutation.setNormalAltCount(8); mutation.setNormalRefCount(18); - mutation.setOncotatorDbSnpRs("rs149680468"); - mutation.setOncotatorCodonChange("c.(133-135)TCT>TTT"); - mutation.setOncotatorRefseqMrnaId("NM_001904"); - mutation.setOncotatorUniprotName("CTNB1_HUMAN"); - mutation.setOncotatorUniprotAccession("P35222"); - mutation.setOncotatorProteinPosStart(666); - mutation.setOncotatorProteinPosEnd(678); + mutation.setCodonChange("c.(133-135)TCT>TTT"); + mutation.setRefseqMrnaId("NM_001904"); + mutation.setUniprotAccession("P35222"); + mutation.setProteinPosStart(666); + mutation.setProteinPosEnd(678); mutation.setCanonicalTranscript(true); mutation.setAnnotationJson(makeMockAnnotationJsonString()); @@ -174,11 +167,6 @@ private void validateMutation(ExtendedMutation mutation) { assertEquals("Broad", mutation.getSequencingCenter()); assertEquals("SOLiD", mutation.getSequencer()); assertEquals("BRCA1_123", mutation.getProteinChange()); - assertEquals("H", mutation.getFunctionalImpactScore()); - assertEquals(Float.MIN_VALUE, mutation.getFisValue(), 1E-30); - assertEquals("link1", mutation.getLinkXVar()); - assertEquals("link2", mutation.getLinkPdb()); - assertEquals("link3", mutation.getLinkMsa()); assertEquals("37/hg19", mutation.getNcbiBuild()); assertEquals("+", mutation.getStrand()); assertEquals("Consolidated", mutation.getVariantType()); @@ -204,13 +192,11 @@ private void validateMutation(ExtendedMutation mutation) { assertEquals(Integer.valueOf(16), mutation.getTumorRefCount()); assertEquals(Integer.valueOf(8), mutation.getNormalAltCount()); assertEquals(Integer.valueOf(18), mutation.getNormalRefCount()); - assertEquals("rs149680468", mutation.getOncotatorDbSnpRs()); - assertEquals("c.(133-135)TCT>TTT", mutation.getOncotatorCodonChange()); - assertEquals("NM_001904", mutation.getOncotatorRefseqMrnaId()); - assertEquals("CTNB1_HUMAN", mutation.getOncotatorUniprotName()); - assertEquals("P35222", mutation.getOncotatorUniprotAccession()); - assertEquals(666, mutation.getOncotatorProteinPosStart()); - assertEquals(678, mutation.getOncotatorProteinPosEnd()); + assertEquals("c.(133-135)TCT>TTT", mutation.getCodonChange()); + assertEquals("NM_001904", mutation.getRefseqMrnaId()); + assertEquals("P35222", mutation.getUniprotAccession()); + assertEquals(666, mutation.getProteinPosStart()); + assertEquals(678, mutation.getProteinPosEnd()); assertEquals(true, mutation.isCanonicalTranscript()); validateMockAnnotationJson(mutation); diff --git a/core/src/test/java/org/mskcc/cbio/portal/stats/TestFisherExact.java b/core/src/test/java/org/mskcc/cbio/portal/stats/TestFisherExact.java index 6139a270c18..06377765dfe 100644 --- a/core/src/test/java/org/mskcc/cbio/portal/stats/TestFisherExact.java +++ b/core/src/test/java/org/mskcc/cbio/portal/stats/TestFisherExact.java @@ -39,7 +39,7 @@ public class TestFisherExact extends TestCase { public void testFisherExact() { FisherExact fisher = new FisherExact(43 + 2 + 17 + 7); - double p = fisher.getCumlativeP(43, 2, 17, 7); + double p = fisher.getTwoTailedP(43, 2, 17, 7); assertEquals(0.006653, p, 0.00001); } } diff --git a/core/src/test/java/org/mskcc/cbio/portal/stats/TestOddsRatio.java b/core/src/test/java/org/mskcc/cbio/portal/stats/TestOddsRatio.java index 3c5b1e73772..108fdb5785e 100644 --- a/core/src/test/java/org/mskcc/cbio/portal/stats/TestOddsRatio.java +++ b/core/src/test/java/org/mskcc/cbio/portal/stats/TestOddsRatio.java @@ -70,9 +70,9 @@ public void testFisherExact() throws IOException { OddsRatio oddsRatio = new OddsRatio(pDataSummary, "BRCA1", "BRCA2"); double oddsRatioValue = oddsRatio.getOddsRatio(); - double p = oddsRatio.getCumulativeP(); + double p = oddsRatio.getTwoTailedP(); assertEquals(0.16666, oddsRatioValue, 0.0001); - assertEquals(0.0849, p, 0.0001); + assertEquals(0.1698, p, 0.0001); //System.out.println (oddsRatio.getRCommand()); } } diff --git a/core/src/test/java/org/mskcc/cbio/portal/util/TestMutationKeywordUtils.java b/core/src/test/java/org/mskcc/cbio/portal/util/TestMutationKeywordUtils.java index 0aaebe64c5c..46bf22e5557 100644 --- a/core/src/test/java/org/mskcc/cbio/portal/util/TestMutationKeywordUtils.java +++ b/core/src/test/java/org/mskcc/cbio/portal/util/TestMutationKeywordUtils.java @@ -107,11 +107,15 @@ public void testGuessCosmicKeyword() throws Exception { assertNull(MutationKeywordUtils.guessCosmicKeyword("K267_D268ins?")); assertNull(MutationKeywordUtils.guessCosmicKeyword("WQQQSYLD25?")); assertNull(MutationKeywordUtils.guessCosmicKeyword("M1>?")); - + assertNull(MutationKeywordUtils.guessCosmicKeyword("PCRF*177delext*4")); //delext deletion should be Null + + // silent assertEquals("*803 silent", MutationKeywordUtils.guessCosmicKeyword("*803*")); assertEquals("A803 silent", MutationKeywordUtils.guessCosmicKeyword("A803A")); assertEquals("A803 silent", MutationKeywordUtils.guessCosmicKeyword("A803>A")); + assertEquals("A803 silent", MutationKeywordUtils.guessCosmicKeyword("A803=")); + assertEquals("A803 silent", MutationKeywordUtils.guessCosmicKeyword("A803%3D")); // missense assertEquals("A2 missense", MutationKeywordUtils.guessCosmicKeyword("A2S")); @@ -127,9 +131,31 @@ public void testGuessCosmicKeyword() throws Exception { assertEquals("630 insertion", MutationKeywordUtils.guessCosmicKeyword("D630_I631insRG")); assertEquals("299 insertion", MutationKeywordUtils.guessCosmicKeyword("299_300insGRS")); assertEquals("976 insertion", MutationKeywordUtils.guessCosmicKeyword("V976_C977ins3")); + assertEquals("172 insertion", MutationKeywordUtils.guessCosmicKeyword("D172_*173insCTSTDGS")); assertEquals("452 insertion", MutationKeywordUtils.guessCosmicKeyword("Y452_Q455>SGGSRIK")); // this is actually missense? assertEquals("475 insertion", MutationKeywordUtils.guessCosmicKeyword("Q475_E476>VLQ")); // this is actually missense? + // extension (treated as insertion) + assertEquals("1001 insertion", MutationKeywordUtils.guessCosmicKeyword("*1001Rext*22")); + + // duplication (treated as insertion) + assertEquals("100 insertion", MutationKeywordUtils.guessCosmicKeyword("A100dup")); + assertEquals("102 insertion", MutationKeywordUtils.guessCosmicKeyword("A102_A104dup")); + + // delins (treated as insertion/missense/deletion) + assertEquals("1038-1041 deletion", MutationKeywordUtils.guessCosmicKeyword("A1038_R1041delinsCFC")); + assertEquals("102-104 deletion", MutationKeywordUtils.guessCosmicKeyword("A102_L104delinsV")); + assertEquals("106 insertion", MutationKeywordUtils.guessCosmicKeyword("A106delinsGRLS")); + assertEquals("106 insertion", MutationKeywordUtils.guessCosmicKeyword("A106_A107delinsGRLS")); + assertEquals("107-108 missense", MutationKeywordUtils.guessCosmicKeyword("A107_L108delinsSD")); + + + // delext (treated as insertion/missense), logically it should only be insertion + assertEquals("125 insertion", MutationKeywordUtils.guessCosmicKeyword("*125delext*8")); + assertEquals("177 insertion", MutationKeywordUtils.guessCosmicKeyword("PCRF*177delext*64")); + assertEquals("177-181 missense", MutationKeywordUtils.guessCosmicKeyword("PCRF*177delext*5")); + + // deletion assertEquals("738-738 deletion", MutationKeywordUtils.guessCosmicKeyword("G738delG")); assertEquals("400-400 deletion", MutationKeywordUtils.guessCosmicKeyword("K400del")); @@ -156,6 +182,7 @@ public void testGuessCosmicKeyword() throws Exception { assertEquals("truncating", MutationKeywordUtils.guessCosmicKeyword("*257fs*>4")); assertEquals("truncating", MutationKeywordUtils.guessCosmicKeyword("557fs*?")); assertEquals("truncating", MutationKeywordUtils.guessCosmicKeyword("?fs")); + assertEquals("truncating", MutationKeywordUtils.guessCosmicKeyword("*100Ifs*4")); assertEquals("truncating", MutationKeywordUtils.guessCosmicKeyword("R412_*413delR*")); assertEquals("truncating", MutationKeywordUtils.guessCosmicKeyword("(P1249)fs*?")); diff --git a/core/src/test/resources/applicationContext-dao.xml b/core/src/test/resources/applicationContext-dao.xml index ba3ced2b03c..0f65a791262 100644 --- a/core/src/test/resources/applicationContext-dao.xml +++ b/core/src/test/resources/applicationContext-dao.xml @@ -67,7 +67,16 @@ - + + + + + mysql + h2 + + + + @@ -76,6 +85,7 @@ + diff --git a/core/src/test/resources/integrationTestScript.xml b/core/src/test/resources/integrationTestScript.xml index 80f4000136a..395272de8cc 100644 --- a/core/src/test/resources/integrationTestScript.xml +++ b/core/src/test/resources/integrationTestScript.xml @@ -35,7 +35,7 @@ --data src/test/resources/genesets/study_es_0_genesets.gmt --new-version - msigdb_6.1 + msigdb_7.5.1 diff --git a/core/src/test/resources/seed_mini.sql b/core/src/test/resources/seed_mini.sql index fd98ec7d340..e17819cfb51 100644 --- a/core/src/test/resources/seed_mini.sql +++ b/core/src/test/resources/seed_mini.sql @@ -419,9 +419,9 @@ INSERT INTO "sample" ("INTERNAL_ID","STABLE_ID","SAMPLE_TYPE","PATIENT_ID") VALU INSERT INTO "sample" ("INTERNAL_ID","STABLE_ID","SAMPLE_TYPE","PATIENT_ID") VALUES (21,'TCGA-A1-A0SB-11','Solid Tissues Normal',20); -- mutation_event -INSERT INTO "mutation_event" ("MUTATION_EVENT_ID","ENTREZ_GENE_ID","CHR","START_POSITION","END_POSITION","REFERENCE_ALLELE","TUMOR_SEQ_ALLELE","PROTEIN_CHANGE","MUTATION_TYPE","FUNCTIONAL_IMPACT_SCORE","FIS_VALUE","LINK_XVAR","LINK_PDB","LINK_MSA","NCBI_BUILD","STRAND","VARIANT_TYPE","DB_SNP_RS","DB_SNP_VAL_STATUS","ONCOTATOR_DBSNP_RS","ONCOTATOR_REFSEQ_MRNA_ID","ONCOTATOR_CODON_CHANGE","ONCOTATOR_UNIPROT_ENTRY_NAME","ONCOTATOR_UNIPROT_ACCESSION","ONCOTATOR_PROTEIN_POS_START","ONCOTATOR_PROTEIN_POS_END","CANONICAL_TRANSCRIPT","KEYWORD") VALUES (2038,672,'17',41244748,41244748,'G','A','Q934*','Nonsense_Mutation','NA',0,'getma.org/?cm=var&var=hg19,17,41244748,G,A&fts=all','NA','NA','37','+','SNP','rs80357223','unknown','rs80357223','NM_007294','c.(2800-2802)CAG>TAG','BRCA1_HUMAN','P38398',934,934,1,'BRCA1 truncating'); -INSERT INTO "mutation_event" ("MUTATION_EVENT_ID","ENTREZ_GENE_ID","CHR","START_POSITION","END_POSITION","REFERENCE_ALLELE","TUMOR_SEQ_ALLELE","PROTEIN_CHANGE","MUTATION_TYPE","FUNCTIONAL_IMPACT_SCORE","FIS_VALUE","LINK_XVAR","LINK_PDB","LINK_MSA","NCBI_BUILD","STRAND","VARIANT_TYPE","DB_SNP_RS","DB_SNP_VAL_STATUS","ONCOTATOR_DBSNP_RS","ONCOTATOR_REFSEQ_MRNA_ID","ONCOTATOR_CODON_CHANGE","ONCOTATOR_UNIPROT_ENTRY_NAME","ONCOTATOR_UNIPROT_ACCESSION","ONCOTATOR_PROTEIN_POS_START","ONCOTATOR_PROTEIN_POS_END","CANONICAL_TRANSCRIPT","KEYWORD") VALUES (22604,672,'17',41258504,41258504,'A','C','C61G','Missense_Mutation','H',4.355,'getma.org/?cm=var&var=hg19,17,41258504,A,C&fts=all','getma.org/pdb.php?prot=BRCA1_HUMAN&from=24&to=64&var=C61G','getma.org/?cm=msa&ty=f&p=BRCA1_HUMAN&rb=24&re=64&var=C61G','37','+','SNP','rs28897672','byCluster','rs28897672','NM_007294','c.(181-183)TGT>GGT','BRCA1_HUMAN','P38398',61,61,1,'BRCA1 C61 missense'); -INSERT INTO "mutation_event" ("MUTATION_EVENT_ID","ENTREZ_GENE_ID","CHR","START_POSITION","END_POSITION","REFERENCE_ALLELE","TUMOR_SEQ_ALLELE","PROTEIN_CHANGE","MUTATION_TYPE","FUNCTIONAL_IMPACT_SCORE","FIS_VALUE","LINK_XVAR","LINK_PDB","LINK_MSA","NCBI_BUILD","STRAND","VARIANT_TYPE","DB_SNP_RS","DB_SNP_VAL_STATUS","ONCOTATOR_DBSNP_RS","ONCOTATOR_REFSEQ_MRNA_ID","ONCOTATOR_CODON_CHANGE","ONCOTATOR_UNIPROT_ENTRY_NAME","ONCOTATOR_UNIPROT_ACCESSION","ONCOTATOR_PROTEIN_POS_START","ONCOTATOR_PROTEIN_POS_END","CANONICAL_TRANSCRIPT","KEYWORD") VALUES (2039,672,'17',41276033,41276033,'C','T','C27_splice','Splice_Site','NA',1.4013e-45,'NA','NA','NA','37','+','SNP','rs80358010','byCluster','rs80358010','NM_007294','c.e2+1','NA','NA',-1,-1,1,'BRCA1 truncating'); +INSERT INTO "mutation_event" ("MUTATION_EVENT_ID","ENTREZ_GENE_ID","CHR","START_POSITION","END_POSITION","REFERENCE_ALLELE","TUMOR_SEQ_ALLELE","PROTEIN_CHANGE","MUTATION_TYPE","NCBI_BUILD","STRAND","VARIANT_TYPE","DB_SNP_RS","DB_SNP_VAL_STATUS","REFSEQ_MRNA_ID","CODON_CHANGE","UNIPROT_ACCESSION","PROTEIN_POS_START","PROTEIN_POS_END","CANONICAL_TRANSCRIPT","KEYWORD") VALUES (2038,672,'17',41244748,41244748,'G','A','Q934*','Nonsense_Mutation','37','+','SNP','rs80357223','unknown','NM_007294','c.(2800-2802)CAG>TAG','P38398',934,934,1,'BRCA1 truncating'); +INSERT INTO "mutation_event" ("MUTATION_EVENT_ID","ENTREZ_GENE_ID","CHR","START_POSITION","END_POSITION","REFERENCE_ALLELE","TUMOR_SEQ_ALLELE","PROTEIN_CHANGE","MUTATION_TYPE","NCBI_BUILD","STRAND","VARIANT_TYPE","DB_SNP_RS","DB_SNP_VAL_STATUS","REFSEQ_MRNA_ID","CODON_CHANGE","UNIPROT_ACCESSION","PROTEIN_POS_START","PROTEIN_POS_END","CANONICAL_TRANSCRIPT","KEYWORD") VALUES (22604,672,'17',41258504,41258504,'A','C','C61G','Missense_Mutation','37','+','SNP','rs28897672','byCluster','NM_007294','c.(181-183)TGT>GGT','P38398',61,61,1,'BRCA1 C61 missense'); +INSERT INTO "mutation_event" ("MUTATION_EVENT_ID","ENTREZ_GENE_ID","CHR","START_POSITION","END_POSITION","REFERENCE_ALLELE","TUMOR_SEQ_ALLELE","PROTEIN_CHANGE","MUTATION_TYPE","NCBI_BUILD","STRAND","VARIANT_TYPE","DB_SNP_RS","DB_SNP_VAL_STATUS","REFSEQ_MRNA_ID","CODON_CHANGE","UNIPROT_ACCESSION","PROTEIN_POS_START","PROTEIN_POS_END","CANONICAL_TRANSCRIPT","KEYWORD") VALUES (2039,672,'17',41276033,41276033,'C','T','C27_splice','Splice_Site','37','+','SNP','rs80358010','byCluster','NM_007294','c.e2+1','NA',-1,-1,1,'BRCA1 truncating'); -- mutation INSERT INTO "mutation" ("MUTATION_EVENT_ID","GENETIC_PROFILE_ID","SAMPLE_ID","ENTREZ_GENE_ID","CENTER","SEQUENCER","MUTATION_STATUS","VALIDATION_STATUS","TUMOR_SEQ_ALLELE1","TUMOR_SEQ_ALLELE2","MATCHED_NORM_SAMPLE_BARCODE","MATCH_NORM_SEQ_ALLELE1","MATCH_NORM_SEQ_ALLELE2","TUMOR_VALIDATION_ALLELE1","TUMOR_VALIDATION_ALLELE2","MATCH_NORM_VALIDATION_ALLELE1","MATCH_NORM_VALIDATION_ALLELE2","VERIFICATION_STATUS","SEQUENCING_PHASE","SEQUENCE_SOURCE","VALIDATION_METHOD","SCORE","BAM_FILE","TUMOR_ALT_COUNT","TUMOR_REF_COUNT","NORMAL_ALT_COUNT","NORMAL_REF_COUNT") VALUES (2038,6,6,672,'genome.wustl.edu','IlluminaGAIIx','Germline','Unknown','G','A','TCGA-A1-A0SH-10A-03D-A099-09','G','A','NA','NA','NA','NA','Unknown','Phase_IV','Capture','NA','1','dbGAP',-1,-1,-1,-1); diff --git a/core/src/test/scripts/test_data/api_json_system_tests/genesets_version.json b/core/src/test/scripts/test_data/api_json_system_tests/genesets_version.json index f60dab80398..204c3d72556 100644 --- a/core/src/test/scripts/test_data/api_json_system_tests/genesets_version.json +++ b/core/src/test/scripts/test_data/api_json_system_tests/genesets_version.json @@ -1 +1 @@ -["msigdb_6.1"] \ No newline at end of file +["msigdb_7.5.1"] \ No newline at end of file diff --git a/core/src/test/scripts/test_data/api_json_unit_tests/genesets_version.json b/core/src/test/scripts/test_data/api_json_unit_tests/genesets_version.json index f60dab80398..204c3d72556 100644 --- a/core/src/test/scripts/test_data/api_json_unit_tests/genesets_version.json +++ b/core/src/test/scripts/test_data/api_json_unit_tests/genesets_version.json @@ -1 +1 @@ -["msigdb_6.1"] \ No newline at end of file +["msigdb_7.5.1"] \ No newline at end of file diff --git a/core/src/test/scripts/test_data/study_es_0/data_structural_variants.txt b/core/src/test/scripts/test_data/study_es_0/data_structural_variants.txt index b5451defa3e..91de51fb735 100644 --- a/core/src/test/scripts/test_data/study_es_0/data_structural_variants.txt +++ b/core/src/test/scripts/test_data/study_es_0/data_structural_variants.txt @@ -1,9 +1,10 @@ Sample_Id Site1_Entrez_Gene_Id Site1_Hugo_Symbol Site1_Ensembl_Transcript_Id Site1_Region_Number Site1_Chromosome Site1_Position Site1_Region Site1_Description Site2_Entrez_Gene_Id Site2_Hugo_Symbol Site2_Ensembl_Transcript_Id Site2_Region_Number Site2_Chromosome Site2_Position Site2_Contig Site2_Region Site2_Description Site2_Effect_On_Frame NCBI_Build DNA_Support RNA_Support Normal_Read_Count Tumor_Read_Count Normal_Variant_Count Tumor_Variant_Count Normal_Paired_End_Read_Count Tumor_Paired_End_Read_Count Normal_Split_Read_Count Tumor_Split_Read_Count Annotation Breakpoint_Type Center Connection_Type Event_Info Class SV_Length Comments External_Annotation cbp_driver cbp_driver_annotation cbp_driver_tiers cbp_driver_tiers_annotation SV_Status StructVarNs.column1 StructVarNs2.lorem StructVarNs.column2 -TCGA-A2-A04P-01 NA KIAA1549 ENST00000242365 15 7 138536968 EXON KIAA1549-BRAF.K16B10.COSF509_1 NA BRAF ENST00000288602 10 7 140482957 EXON KIAA1549-BRAF.K16B10.COSF509_2 NA GRCh37 no yes NA 1000 NA 900 NA NA NA NA KIAA1549-BRAF.K16B10.COSF509 NA NA NA Fusion NA NA Gain-of-Function COSMIC:COSF509 NA NA NA NA SOMATIC value1 ipsum value2 -TCGA-A2-A04P-01 NA NCOA4 ENST00000344348 7 10 51582939 EXON NCOA4-RET.N7R12_1 NA RET ENST00000340058 12 10 43612031 EXON NCOA4-RET.N7R12_2 NA GRCh37 no yes NA 1001 NA 800 NA NA NA NA NCOA4-RET.N7R1 NA NA NA Fusion NA NA Gain-of-Function NA NA NA NA NA SOMATIC -TCGA-A2-A04P-01 NA EML4 ENST00000318522 6 2 42492091 EXON EML4-ALK.E6bA20.AB374362_1 NA ALK ENST00000389048 20 2 29446394 EXON EML4-ALK.E6bA20.AB374362_2 NA GRCh37 no yes NA 1002 NA 700 NA NA NA NA EML4-ALK.E6bA20.AB374362 NA NA NA Fusion NA NA Gain-of-Function GENBANK:AB374362 NA NA NA NA SOMATIC -TCGA-A2-A04P-01 NA TMPRSS2 ENST00000332149 1 21 42880007 EXON TMPRSS2-ERG.T1E2.COSF23.1_1 NA ERG ENST00000442448 2 21 39956869 EXON TMPRSS2-ERG.T1E2.COSF23.1_2 NA GRCh37 no yes NA 1003 NA 600 NA NA NA NA TMPRSS2-ERG.T1E2.COSF23.1 NA NA NA Fusion NA NA Gain-of-Function COSMIC:COSF23 NA NA NA NA SOMATIC -TCGA-A2-A04P-01 NA EGFR ENST00000275493 1 7 55087058 EXON EGFR-EGFR.E1E8.DelPositive.1_1 NA EGFR ENST00000275493 8 7 55223522 EXON EGFR-EGFR.E1E8.DelPositive.1_2 NA GRCh37 no yes NA 1004 NA 500 NA NA NA NA EGFR-EGFR.E1E8.DelPositive NA NA NA Fusion NA NA NA NA NA NA NA NA SOMATIC +TCGA-A2-A04P-01 NA PIEZO1 ENST00000242365 15 7 138536968 EXON PIEZO1-NCOA4.K16B10.COSF509_1 NA NCOA4 ENST00000288602 10 7 140482957 EXON PIEZO1-NCOA4.PIEZO1.COSF509_2 NA GRCh37 no yes NA 1000 NA 900 NA NA NA NA PIEZO1-NCOA4.K16B10.COSF509 NA NA NA Fusion NA NA Gain-of-Function COSMIC:COSF509 Putative_Driver Test driver Foo Class 4 Class annotation SOMATIC value1 ipsum value2 +TCGA-A2-A04P-01 NA KIAA1549 ENST00000242365 15 7 138536968 EXON KIAA1549-BRAF.K16B10.COSF509_1 NA BRAF ENST00000288602 10 7 140482957 EXON KIAA1549-BRAF.K16B10.COSF509_2 NA GRCh37 no yes NA 1000 NA 900 NA NA NA NA KIAA1549-BRAF.K16B10.COSF509 NA NA NA Fusion NA NA Gain-of-Function COSMIC:COSF509 Putative_Driver Test driver Class 4 Class annotation SOMATIC value1 ipsum value2 +TCGA-A2-A04P-01 NA NCOA4 ENST00000344348 7 10 51582939 EXON NCOA4-RET.N7R12_1 NA RET ENST00000340058 12 10 43612031 EXON NCOA4-RET.N7R12_2 NA GRCh37 no yes NA 1001 NA 800 NA NA NA NA NCOA4-RET.N7R1 NA NA NA Fusion NA NA Gain-of-Function NA Putative_Passenger Test driver Class 3 Class annotation SOMATIC +TCGA-A2-A04P-01 NA EML4 ENST00000318522 6 2 42492091 EXON EML4-ALK.E6bA20.AB374362_1 NA ALK ENST00000389048 20 2 29446394 EXON EML4-ALK.E6bA20.AB374362_2 NA GRCh37 no yes NA 1002 NA 700 NA NA NA NA EML4-ALK.E6bA20.AB374362 NA NA NA Fusion NA NA Gain-of-Function GENBANK:AB374362 Putative_Driver Test driver Class 2 Class annotation SOMATIC +TCGA-A2-A04P-01 NA TMPRSS2 ENST00000332149 1 21 42880007 EXON TMPRSS2-ERG.T1E2.COSF23.1_1 NA ERG ENST00000442448 2 21 39956869 EXON TMPRSS2-ERG.T1E2.COSF23.1_2 NA GRCh37 no yes NA 1003 NA 600 NA NA NA NA TMPRSS2-ERG.T1E2.COSF23.1 NA NA NA Fusion NA NA Gain-of-Function COSMIC:COSF23 Unknown Test driver Class 1 Class annotation SOMATIC +TCGA-A2-A04P-01 NA EGFR ENST00000275493 1 7 55087058 EXON EGFR-EGFR.E1E8.DelPositive.1_1 NA EGFR ENST00000275493 8 7 55223522 EXON EGFR-EGFR.E1E8.DelPositive.1_2 NA GRCh37 no yes NA 1004 NA 500 NA NA NA NA EGFR-EGFR.E1E8.DelPositive NA NA NA Fusion NA NA NA NA Putative_Driver Test driver Unknown Class annotation SOMATIC TCGA-A2-A04P-01 NA ALK ENST00000389048 11 2 29497964 EXON ALK-PTPN3.A11P3_1 NA PTPN3 ENST00000374541 3 9 112219679 EXON ALK-PTPN3.A11P3_2 NA GRCh37 no yes NA 1005 NA 400 NA NA NA NA ALK-PTPN3.A11P3 NA NA NA Fusion NA NA NA NA NA NA NA NA SOMATIC TCGA-A1-A0SB-01 NA EML4 ENST00000318522 13 2 42522656 EXON EML4-ALK.E13A20.AB462411_1 NA ALK ENST00000389048 20 2 29446335 EXON EML4-ALK.E13A20.AB462411_2 NA GRCh37 no yes NA 1006 NA 300 NA NA NA NA EML4-ALK.E13A20 NA NA NA Fusion NA NA Gain-of-Function GENBANK:AB462411 NA NA NA NA SOMATIC TCGA-A1-A0SB-01 NA TMPRSS2 ENST00000455813 1 21 42870045 EXON TMPRSS2-ETV1.T1bE4_1 NA ETV1 ENST00000405358 4 7 14017105 EXON TMPRSS2-ETV1.T1bE4_2 NA GRCh37 no yes NA 1007 NA 200 NA NA NA NA TMPRSS2-ETV1.T1bE4 NA NA NA Fusion NA NA NA NA NA NA NA NA SOMATIC @@ -44,3 +45,5 @@ TCGA-A2-A04Q-01 NA SND1 ENST00000354725 10 1 10000000 EXON SND1_BRAF_CUSTOMHYVE_ TCGA-A2-A0SX-01 NA MKRN1 ENST00000255977 4 1 10000000 EXON MKRN1_BRAF_CUSTOMHYVE_1 NA BRAF ENST00000288602 11 1 10000000 EXON MKRN1_BRAF_CUSTOMHYVE_2 NA GRCh37 no yes NA 1000 NA 900 NA NA NA NA MKRN1_BRAF_CUSTOMHYVE NA NA NA Fusion NA NA Gain-of-Function NA NA NA NA NA SOMATIC TCGA-AO-A0JL-01 NA MKRN1 ENST00000255977 4 1 10000000 EXON MKRN1_BRAF_CUSTOMHYVE_1 NA BRAF ENST00000288602 11 1 10000000 EXON MKRN1_BRAF_CUSTOMHYVE_2 NA GRCh37 no yes NA 1000 NA 900 NA NA NA NA MKRN1_BRAF_CUSTOMHYVE NA NA NA Fusion NA NA Gain-of-Function NA NA NA NA NA SOMATIC TCGA-AO-A0JL-01 NA BRAF ENST00000288602 6 1 10000000 EXON BRAF_TTN_CUSTOMHYVE_1 NA TTN ENST00000589042 2 1 111111111 EXON BRAF_TTN_CUSTOMHYVE_2 NA GRCh37 no yes NA 1000 NA 900 NA NA NA NA BRAF_TTN_CUSTOMHYVE NA NA NA Fusion NA NA Gain-of-Function NA NA NA NA NA SOMATIC +TCGA-AO-A0JL-01 NA BRAF ENST00000288602 6 1 10000000 EXON BRAF_NULL_CUSTOMHYVE_1 NA 2 1 111111111 EXON BRAF_NULL_CUSTOMHYVE_2 NA GRCh37 no yes NA 1000 NA 900 NA NA NA NA BRAF_NULL_CUSTOMHYVE NA NA NA Fusion NA NA Gain-of-Function NA NA NA NA NA SOMATIC +TCGA-AO-A0JL-01 NA 6 1 10000000 EXON NULL_TTN_CUSTOMHYVE_1 NA TTN ENST00000589042 2 1 111111111 EXON NULL_TTN_CUSTOMHYVE_2 NA GRCh37 no yes NA 1000 NA 900 NA NA NA NA NULL_TTN_CUSTOMHYVE NA NA NA Fusion NA NA Gain-of-Function NA NA NA NA NA SOMATIC diff --git a/core/src/test/scripts/test_data/study_es_0/meta_gsva_pvalues.txt b/core/src/test/scripts/test_data/study_es_0/meta_gsva_pvalues.txt index ee985fbf4d4..59b8254cd8d 100644 --- a/core/src/test/scripts/test_data/study_es_0/meta_gsva_pvalues.txt +++ b/core/src/test/scripts/test_data/study_es_0/meta_gsva_pvalues.txt @@ -6,4 +6,4 @@ source_stable_id: gsva_scores profile_name: Pvalues of GSVA scores on oncogenic signatures gene sets profile_description: Pvalues GSVA scores using mRNA expression data data_filename: data_gsva_pvalues.txt -geneset_def_version: msigdb_6.1 +geneset_def_version: msigdb_7.5.1 diff --git a/core/src/test/scripts/test_data/study_es_0/meta_gsva_scores.txt b/core/src/test/scripts/test_data/study_es_0/meta_gsva_scores.txt index ff6a143f386..16874d408a9 100644 --- a/core/src/test/scripts/test_data/study_es_0/meta_gsva_scores.txt +++ b/core/src/test/scripts/test_data/study_es_0/meta_gsva_scores.txt @@ -7,4 +7,4 @@ profile_name: GSVA scores on oncogenic signatures gene sets profile_description: GSVA scores using mRNA expression data data_filename: data_gsva_scores.txt show_profile_in_analysis_tab: true -geneset_def_version: msigdb_6.1 +geneset_def_version: msigdb_7.5.1 diff --git a/core/src/test/scripts/test_data/study_es_0/result_report.html b/core/src/test/scripts/test_data/study_es_0/result_report.html index 00133e553f9..8a39412f12d 100644 --- a/core/src/test/scripts/test_data/study_es_0/result_report.html +++ b/core/src/test/scripts/test_data/study_es_0/result_report.html @@ -1742,7 +1742,7 @@

data_resource_study.txt

- 3 + 5

data_structural_variants.txt

@@ -1770,6 +1770,22 @@

data_structural_variants.txt

– + + Info + 48 + – + No Entrez gene id or gene symbol provided for site 2. Assuming either the intragenic, deletion, duplication, translocation or inversion variant + – + + + + Info + 49 + – + No Entrez gene id or gene symbol provided for site 1. Assuming either the intragenic, deletion, duplication, translocation or inversion variant + – + + Info – @@ -1782,7 +1798,7 @@

data_structural_variants.txt

Info – – - Read 46 lines. Lines with warning: 0. Lines with error: 0 + Read 49 lines. Lines with warning: 0. Lines with error: 0 – diff --git a/db-scripts/src/main/resources/cgds.sql b/db-scripts/src/main/resources/cgds.sql index 1871b709a0e..2971b3d1be6 100644 --- a/db-scripts/src/main/resources/cgds.sql +++ b/db-scripts/src/main/resources/cgds.sql @@ -436,23 +436,16 @@ CREATE TABLE `mutation_event` ( `TUMOR_SEQ_ALLELE` text, `PROTEIN_CHANGE` varchar(255), `MUTATION_TYPE` varchar(255) COMMENT 'e.g. Missense, Nonsence, etc.', - `FUNCTIONAL_IMPACT_SCORE` varchar(50) COMMENT 'Result from OMA/XVAR.', - `FIS_VALUE` float, - `LINK_XVAR` varchar(500) COMMENT 'Link to OMA/XVAR Landing Page for the specific mutation.', - `LINK_PDB` varchar(500), - `LINK_MSA` varchar(500), `NCBI_BUILD` varchar(10), `STRAND` varchar(2), `VARIANT_TYPE` varchar(15), `DB_SNP_RS` varchar(25), `DB_SNP_VAL_STATUS` varchar(255), - `ONCOTATOR_DBSNP_RS` varchar(255), - `ONCOTATOR_REFSEQ_MRNA_ID` varchar(64), - `ONCOTATOR_CODON_CHANGE` varchar(255), - `ONCOTATOR_UNIPROT_ENTRY_NAME` varchar(64), - `ONCOTATOR_UNIPROT_ACCESSION` varchar(64), - `ONCOTATOR_PROTEIN_POS_START` int(11), - `ONCOTATOR_PROTEIN_POS_END` int(11), + `REFSEQ_MRNA_ID` varchar(64), + `CODON_CHANGE` varchar(255), + `UNIPROT_ACCESSION` varchar(64), + `PROTEIN_POS_START` int(11), + `PROTEIN_POS_END` int(11), `CANONICAL_TRANSCRIPT` boolean, `KEYWORD` varchar(255) DEFAULT NULL COMMENT 'e.g. truncating, V200 Missense, E338del, ', KEY (`KEYWORD`), @@ -762,5 +755,5 @@ CREATE TABLE `resource_study` ( ); -- THIS MUST BE KEPT IN SYNC WITH db.version PROPERTY IN pom.xml -INSERT INTO info VALUES ('2.12.16', NULL); +INSERT INTO info VALUES ('2.13.1', NULL); diff --git a/db-scripts/src/main/resources/migration.sql b/db-scripts/src/main/resources/migration.sql index ef820bb95a5..78c0d25ea14 100644 --- a/db-scripts/src/main/resources/migration.sql +++ b/db-scripts/src/main/resources/migration.sql @@ -978,6 +978,8 @@ UPDATE `info` SET `DB_SCHEMA_VERSION`="2.12.12"; ALTER TABLE `sample` MODIFY COLUMN `STABLE_ID` VARCHAR(63) NOT NULL; UPDATE `info` SET `DB_SCHEMA_VERSION`="2.12.13"; + + ##version: 2.12.14 ALTER TABLE `structural_variant` MODIFY COLUMN `SITE1_ENTREZ_GENE_ID` int(11); ALTER TABLE `structural_variant` ADD COLUMN `SITE1_REGION` varchar(25) AFTER `SITE1_CHROMOSOME`; @@ -1000,3 +1002,29 @@ UPDATE `info` SET `DB_SCHEMA_VERSION`="2.12.15"; ##version: 2.12.16 ALTER TABLE `structural_variant` ADD COLUMN `ANNOTATION_JSON` JSON AFTER `SV_STATUS`; UPDATE `info` SET `DB_SCHEMA_VERSION`="2.12.16"; + +##version: 2.13.0 +-- changes for issue 9461 +ALTER TABLE `mutation_event` DROP COLUMN `FUNCTIONAL_IMPACT_SCORE`; +ALTER TABLE `mutation_event` DROP COLUMN `FIS_VALUE`; +ALTER TABLE `mutation_event` DROP COLUMN `LINK_XVAR`; +ALTER TABLE `mutation_event` DROP COLUMN `LINK_PDB`; +ALTER TABLE `mutation_event` DROP COLUMN `LINK_MSA`; + +-- changes for issue 9779 +ALTER TABLE `mutation_event` DROP COLUMN `ONCOTATOR_DBSNP_RS`; +ALTER TABLE `mutation_event` DROP COLUMN `ONCOTATOR_UNIPROT_ENTRY_NAME`; +ALTER TABLE `mutation_event` CHANGE COLUMN `ONCOTATOR_REFSEQ_MRNA_ID` `REFSEQ_MRNA_ID` varchar(64); +ALTER TABLE `mutation_event` CHANGE COLUMN `ONCOTATOR_CODON_CHANGE` `CODON_CHANGE` varchar(255); +ALTER TABLE `mutation_event` CHANGE COLUMN `ONCOTATOR_UNIPROT_ACCESSION` `UNIPROT_ACCESSION` varchar(64); +ALTER TABLE `mutation_event` CHANGE COLUMN `ONCOTATOR_PROTEIN_POS_START` `PROTEIN_POS_START` int(11); +ALTER TABLE `mutation_event` CHANGE COLUMN `ONCOTATOR_PROTEIN_POS_END` `PROTEIN_POS_END` int(11); +UPDATE `info` SET `DB_SCHEMA_VERSION`="2.13.0"; + + +##version: 2.13.1 +ALTER TABLE `clinical_event_data` MODIFY COLUMN `VALUE` varchar(3000) NOT NULL; +CREATE INDEX idx_clinical_event_key ON clinical_event_data (`KEY`); +CREATE INDEX idx_clinical_event_value ON clinical_event_data (`VALUE`); +CREATE INDEX idx_sample_stable_id ON sample (`STABLE_ID`); +UPDATE `info` SET `DB_SCHEMA_VERSION`="2.13.1"; \ No newline at end of file diff --git a/docker/web-and-data/docker-entrypoint.sh b/docker/web-and-data/docker-entrypoint.sh index 84951a53358..b474a216d5b 100755 --- a/docker/web-and-data/docker-entrypoint.sh +++ b/docker/web-and-data/docker-entrypoint.sh @@ -3,7 +3,7 @@ set -eo pipefail shopt -s nullglob BAKED_IN_WAR_CONFIG_FILE=/cbioportal-webapp/WEB-INF/classes/portal.properties -CUSTOM_PROPERTIES_FILE=/cbioportal/portal.properties +CUSTOM_PROPERTIES_FILE=cbioportal/portal.properties # check to see if this file is being run or sourced from another script _is_sourced() { @@ -23,19 +23,57 @@ parse_db_params_from_config_and_command_line() { else PROPERTIES_FILE=$BAKED_IN_WAR_CONFIG_FILE fi - - for param in db.host db.user db.portal_db_name db.password; do + for param in db.host db.user db.portal_db_name db.password db.connection_string; do if $(parse_db_params_from_command_line $@ | grep -q $param); then - parse_db_params_from_command_line $@ | grep "^$param" + prop=$(parse_db_params_from_command_line $@ | grep "^$param" || [[ $? == 1 ]]) else - grep -v '^#' $PROPERTIES_FILE | grep "^$param" + prop=$(grep -v '^#' $PROPERTIES_FILE | grep "^$param" || [[ $? == 1 ]]) + fi + if [[ -n "$prop" ]] + then + # Replace dot in parameter name with underscore. + prop=$(sed "s/^db\./db_/" <<< $prop) + if [[ $param == db.connection_string ]] + then + # Remove the parameters (?...) from the connection URL. + echo $(sed -r "s/^([^=]+)=([^\?]+).*/\1=\2/" <<< $prop) + else + echo $prop + fi fi done } +parse_connection_string() { + # Adapted from: https://stackoverflow.com/a/45977232 + readonly URI_REGEX='^(([^:/?#]+):)+?(//((([^:/?#]+)@)?([^:/?#]+)(:([0-9]+))?))?(/([^?#]*))(\?([^#]*))?(#(.*))?' + # ↑↑ ↑ ↑↑↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ + # |2 scheme | ||6 userinfo 7 host | 9 port | 11 rpath | 13 query | 15 fragment + # 1 scheme: | |5 userinfo@ 8 :… 10 path 12 ?… 14 #… + # | 4 authority + # 3 //… + echo db_host=$([[ "$1" =~ $URI_REGEX ]] && echo "${BASH_REMATCH[7]}") + echo db_port=$([[ "$1" =~ $URI_REGEX ]] && echo "${BASH_REMATCH[9]}") +} + check_db_connection() { - eval "$(parse_db_params_from_config_and_command_line $@ | sed 's/^db\./db_/g')" - POTENTIAL_DB_PARAMS=$@ + eval $(parse_db_params_from_config_and_command_line $@) + + if [[ -n $db_host ]] || [[ -n $db_portal_db_name ]] || [[ -n $db_use_ssl ]] + then + echo "----------------------------------------------------------------------------------------------------------------" + echo "-- Connection error:" + echo "-- You try to connect to the database using the deprecated 'db.host', 'db.portal_db_name' and 'db.use_ssl' properties." + echo "-- Please remove these properties and use the 'db.connection_string' property instead. See https://docs.cbioportal.org/deployment/customization/portal.properties-reference/" + echo "-- for assistance on building a valid connection string." + echo "------------------------------------------------------------f---------------------------------------------------" + exit 1 + fi + + if [[ -n $db_connection_string ]] + then + eval "$(parse_connection_string $db_connection_string)" + fi if [ -z ${db_port+x} ] # is $db_port unset? then @@ -46,7 +84,6 @@ check_db_connection() { fi fi - while ! mysqladmin ping -s -h$(echo ${db_host} | cut -d: -f1) -P${db_port} -u${db_user} -p${db_password}; do sleep 5s; diff --git a/docs/About-Us.md b/docs/About-Us.md index 74d3d1c7aba..0559b662457 100644 --- a/docs/About-Us.md +++ b/docs/About-Us.md @@ -3,9 +3,7 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K ## Memorial Sloan Kettering Cancer Center * Benjamin Gross * S Onur Sumer -* Yichao Sun * Hongxin Zhang -* Adam Abeshouse * Ritika Kundra * Ino de Bruijn * Robert Sheridan @@ -16,13 +14,16 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K * Ramyasree Madupuri * Gaofei Zhao * Xiang Li +* Bryan Lai +* Calla Chennault * Anusha Satravada -* Divya Madala +* Rima AlHamad * Nikolaus Schultz ## Dana-Farber Cancer Institute * Ethan Cerami * Tali Mazor +* Jeremy Easton-Marks * Zhaoyuan (Ryan) Fu * Augustin Luna * James Lindsay @@ -38,10 +39,12 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K * Allison Heath * John Maris * Adam Resnick +* Miguel Brown ## Caris Life Sciences * Jianjiong Gao * Priti Kumari +* Karthik Kalletla ## The Hyve * Oleguer Plantalech @@ -61,10 +64,12 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K ## Bilkent University * Ugur Dogrusoz -* M Salih Altun +* Yusuf Ziya Ozgul ## Alumni +* Adam Abeshouse * B Arman Aksoy +* M Salih Altun * Istemi Bahceci * Caitlin Byrne * Hsiao-Wei Chen @@ -80,11 +85,11 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K * Zachary Heins * Michael Heuer * Anders Jacobsen -* Karthik Kalletla +* Peter Kok * Erik Larsson * Dong Li +* Divya Madala * Tamba Monrose -* Peter Kok * Irina Pulyakhina * Pichai Raman * M Furkan Sahin @@ -92,6 +97,7 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K * Alexandros Sigaras * Luke Sikina * Jing Su +* Yichao Sun * Sander Tan * Jiaojiao Wang * Stuart Watt diff --git a/docs/File-Formats.md b/docs/File-Formats.md index 37592f25ebc..325eefbde62 100644 --- a/docs/File-Formats.md +++ b/docs/File-Formats.md @@ -21,6 +21,7 @@ * [Study Tags file](#study-tags-file) * [Generic Assay](#generic-assay) * [Arm Level CNA Data](#arm-level-cna-data) + * [Mutational Signature Data](#mutational-signature-data) * [Resource Data](#resource-data) * [Custom namespace columns](#custom-namespace-columns) @@ -1416,7 +1417,7 @@ profile_name: GSVA scores on oncogenic signatures gene sets profile_description: GSVA scores on oncogenic signatures gene sets using mRNA expression data calculated with GSVA version x with parameters x and y. data_filename: data_gsva_scores.txt show_profile_in_analysis_tab: true -geneset_def_version: msigdb_6.1 +geneset_def_version: msigdb_7.5.1 ``` ### GSVA score data file @@ -1460,7 +1461,7 @@ source_stable_id: gsva_scores profile_name: GSVA p-values for GSVA scores on oncogenic signatures gene sets profile_description: GSVA p-values for GSVA scores on oncogenic signatures gene sets using mRNA expression data calculated with the bootstrapping method in GSVA version x with parameters x and y. data_filename: data_gsva_pvalues.txt -geneset_def_version: msigdb_6.1 +geneset_def_version: msigdb_7.5.1 ``` ### GSVA p-value data file @@ -1599,6 +1600,32 @@ Allowed values for Arm-level copy-number data are `Loss`, `Gain`, and `Unchanged Please find example file format here: [Meta file example](https://github.com/cBioPortal/cbioportal-frontend/blob/master/end-to-end-test/local/studies/lgg_ucsf_2014_test_generic_assay/meta_armlevel_CNA.txt) and [Data file example](https://github.com/cBioPortal/cbioportal-frontend/blob/master/end-to-end-test/local/studies/lgg_ucsf_2014_test_generic_assay/data_armlevel_CNA.txt) +### Mutational Signature Data +Mutational Signature data is a predefined subtype of Generic Assay Data. Setting `generic_assay_type: MUTATIONAL_SIGNATURE` +in the meta file will make cBioPortal interpret the data as Mutational Signature data. + +#### Mutational Signature meta files +The mutational signature meta files follow the same convention as the [Generic Assay Meta file](#generic-assay-meta-file), +however there are some key differences: +- `genetic_assay_type` should be set to `MUTATIONAL_SIGNATURE` +- `datatype` should be set to `LIMIT_VALUE` +- `stable_id` values should end with: `_{filetype}_{identifier}`, where: + - `filetype` is either `contribution`, `pvalue` or `counts` + - `identifier` is consistent between files belonging to the same analysis + - Multiple signatures can be added to a single study, as long as they have different identifiers in their stable id (e.g., `contribution_SBS` and `contribution_DBS`) +- In `generic_entity_meta_properties` the `NAME` value is required. The `DESCRIPTION` and `URL` values can be added + to display more information and link to external resources in the mutational signatures tab. + +#### Mutational Signature data files +The mutational signature data files follow the same convention as the [Generic Assay Data file](#generic-assay-data-file). +Each collection of mutational signatures can consist of up to three different data files, each with an accompanying meta file. +- Signature _contribution_ file (**required**) + - Data file containing the contribution of each signature-sample pair. Values are expected to be 0 ≥ x ≥ 1. +- Signature _pvalue_ file (optional) + - Data file containing p-values for each signature-sample pair. Values below 0.05 will be shown as significant. +- Mutational _counts_ matrix file (optional) + - Data file containing nucleotide changes of a sample. cBioPortal has specific visualization options for single-base substitutions (96 channels), double-base substitutions (72 channels) and insertion/deletions (83 channels), following the signatures defined by [COSMIC](https://cancer.sanger.ac.uk/signatures/). But other channels can also be used. Values are expected to be positive integers. + ## Resource Data The resource data is used to capture resource data in patients, samples and studies. The resources will be represented by URLs with meta data. The types of resources include: diff --git a/docs/Imported-MAF-Columns.md b/docs/Imported-MAF-Columns.md index 43ff6bb47d6..da449abf013 100644 --- a/docs/Imported-MAF-Columns.md +++ b/docs/Imported-MAF-Columns.md @@ -69,11 +69,6 @@ Relevant classes: | ONCOTATOR_CODON_CHANGE | ONCOTATOR_CODON_CHANGE | | mutation_event.oncotator_codon_change ** [maps to DB but MAF value never imported] | see ImportExtendedMutation (codonChange = record.getCodons()) / MAF field "Codons" always overrides MAF value ONCOTATOR_CODON_CHANGE // "ONCOTATOR_CODON_CHANGE" never used? / MafRecord (record.getOncotatorCodonChange()) never used | | ONCOTATOR_PROTEIN_POS_START | ONCOTATOR_PROTEIN_POS_START | | mutation_event.oncotator_protein_pos_start ** [maps to DB but MAF value never imported] | see ExtendedMutationUtil.getProteinPosStart() / resolved from record.getProteinPosition() or record.getProteinChange() based on what is avialable / MAF field "ONCOTATOR_PROTEIN_POS_START" never used? | | ONCOTATOR_PROTEIN_POS_END | ONCOTATOR_PROTEIN_POS_END | | mutation_event.oncotator_protein_pos_end ** [maps to DB but MAF value never imported] | see ExtendedMutationUtil.getProteinPosStart() / resolved from record.getProteinPosition() or record.getProteinChange() based on what is avialable / MAF field "ONCOTATOR_PROTEIN_POS_END" never used? | -| MA_FIMPACT | MA:FImpact | | mutation_event.functional_impact_score | | -| MA_FIS | MA:FIS | | mutation_event.fis_value | | -| MA_LINK_VAR | MA:link.var | | mutation_event.link_xvar | | -| MA_LINK_MSA | MA:link.MSA | | mutation_event.link_msa | | -| MA_LINK_PDB | MA:link.PDB | | mutation_event.link_pdb | | | DRIVER_FILTER | cbp_driver | mutation.driver_filter | | | | DRIVER_FILTER_ANNOTATION | cbp_driver_annotation | mutation.driver_filter_annotation | | | | DRIVER_TIERS_FILTER | cbp_driver_tiers | mutation.driver_tiers_filter | | | diff --git a/docs/MSK-Maintenance.md b/docs/MSK-Maintenance.md new file mode 100644 index 00000000000..159200f199c --- /dev/null +++ b/docs/MSK-Maintenance.md @@ -0,0 +1,70 @@ +# MSK Maintenance (In Progress) +We provide our cBioPortal's maintenance page publicly in the hope that it may be useful to others + +## Database Migration +In the database migration process, we are going to have two main steps: building importers and updating database scheme. + +### Building Importers +- Codebases: + - [cbioportal](https://github.com/cBioPortal/cbioportal) + - [genome nexus annotation pipeline](https://github.com/genome-nexus/genome-nexus-annotation-pipeline) + - [pipelines](https://github.com/knowledgesystems/pipelines) +- Building single importer: + - Take the cbioportal hash and add it to genome nexus annotation pipeline POM -> push to fork + - Take the cbioportal hash and new genome nexus annotation pipeline hash (from above) and propagate to pipelines POM; also update db version if db migration is part of change + - Login to pipelines server + - Sets general env variables needed for building + - Run `sh /data/portal-con/scripts/automation-environment.sh` + - Specific to cbioportal build, looks for properties and xml files off of $PORTAL_HOME + - Run `export PORTAL_HOME=/data/portal-cron/git-repos/cbioportal` + - Make sure the local cbioportal codebase is on the correct git hash at `/data/portal-cron/git-repos/cbioportal` + - Specify importer to be build + - Copy importer properties to `/data/portal-con-git-repos/cbioportal/src/main/resources` (e.g. triage `/data/portal-cron/git-repos/pipelines-configuration/properties/import-triage/*`) + - Navigate to pipelines folder + - `cd /data/portal-con/git-repos/pipelines` + - Build importer + - mvn clean install -DskipTests +- Build multiple importers + - Take the cbioportal hash and add it to genome nexus annotation pipeline POM -> push to fork + - Take the cbioportal hash and new genome nexus annotation pipeline hash (from above) and propagate to pipelines POM; also update db version if db migration is part of change + - Login to pipelines server + - Sets general env variables needed for building + - Run `sh /data/portal-con/scripts/automation-environment.sh` + - Specific to cbioportal build, looks for properties and xml files off of $PORTAL_HOME + - Run `export PORTAL_HOME=/data/portal-cron/git-repos/cbioportal` + - Make sure the local cbioportal codebase is on the correct git hash at `/data/portal-cron/git-repos/cbioportal` + - Go to build importer jars folder + - `cd /data/portal-cron/git-repo/pipelines-configuration/build-importer-jars` + - (Optional) Remove existing jars + - `rm *.jar` + - Build all importers at once (build all importers except cmo-pipelines) + - `sh buildproductionjars.sh -sd=true -sgp=true -b=importers` + - Available parameters: + - [--cbioportal-git-hash|-cgh=] + - [--skip-deployment|-sd=] + - [--skip-git-pull|-sgp=] + - [--build|-b=], build_specifier should be one of the following + - all (build for all artifacts) + - importers (all importers except cmo-pipelines) + - cmo-pipelines (cmo-pipelines artifacts only) + - triage-cmo-importer + - msk-dmp-importer + - msk-cmo-importer + - public-importer + - genie-aws-importer + - genie-archive-importer + - hgnc-importer + +### Updating Database Scheme +Database needs to be updated one by one, we have four main databases: triage, private, genie, and public. Take triage database as an example. +- Migrate one database (e.g. triage) + - SSH into pipeline server + - Checkout to the commit that contains the latest database scheme + - Check if property sets up correctly to the right database (triage) + - `vi /data/portal-con-git-repos/cbioportal/src/main/resources/portal.properties` + - Move to directory + - `cd /data/portal-con-git-repos/cbioportal` + - Run database migration using script: + - `python3 core/src/main/scripts/migrate_db.py --properties-file src/main/resources/portal.properties --sql db-scripts/src/main/resources/migration.sql` + - Monitor the DB migration process and look for possible errors + - Access database and verify the DB scheme is updated diff --git a/docs/Migration-Guide.md b/docs/Migration-Guide.md index 7e5ce3197bb..624124f75fc 100644 --- a/docs/Migration-Guide.md +++ b/docs/Migration-Guide.md @@ -1,22 +1,45 @@ # Migration Guide -This page describes various changes deployers will need to make as they deploy newer versions of the portal. + +This page describes various changes deployers will need to make as they deploy newer versions of the portal. - + +## v5.3 -> v5.4 + +- Remove `db.host` and `db.portal_db_name` and `db.use_ssl` properties from the _portal.properties_ file or JVM + parameters. Update property `db.connection_string` to encode the hostname, port, database and other parameters + according to [Database Settings](deployment/customization/portal.properties-Reference.md#Database-Settings) documentation and pass via + _portal.properties_ file or as JVM parameter. ## v4 -> v5 -- All fusion profiles are now required to be migrated to structural variant format. One can use this [migration tool](https://github.com/cBioPortal/datahub-study-curation-tools/tree/master/fusion-to-sv-converter) to migrate the fusion files. -- All fusion files on [datahub](https://github.com/cBioPortal/datahub) were migrated to the structural variant format and their molecular profile ids were renamed from `{study_id}_fusion` to `{study_id}_structural_variants`. If you are using these datahub files one would need to re-import them. -- Study view user setting will be outdated after migration, please follow `Clear Study View User settings` section in [Session Service Management](Session-Service-Management.md#Clear-Study-View-User-settings) -- The new default set of transcripts for each gene has changed from `uniprot` to `mskcc`. See the [Mutation Data Annotation Section](./mutation-data-transcript-annotation.md) for more details. To keep the old set of default transcripts add the property `genomenexus.isoform_override_source=uniprot` to [the properties file](https://docs.cbioportal.org/deployment/customization/portal.properties-reference/#properties). + +- All fusion profiles are now required to be migrated to structural variant format. One can use + this [migration tool](https://github.com/cBioPortal/datahub-study-curation-tools/tree/master/fusion-to-sv-converter) + to migrate the fusion files. +- All fusion files on [datahub](https://github.com/cBioPortal/datahub) were migrated to the structural variant format + and their molecular profile ids were renamed from `{study_id}_fusion` to `{study_id}_structural_variants`. If you are + using these datahub files one would need to re-import them. +- Study view user setting will be outdated after migration, please follow `Clear Study View User settings` section + in [Session Service Management](Session-Service-Management.md#Clear-Study-View-User-settings) +- The new default set of transcripts for each gene has changed from `uniprot` to `mskcc`. See + the [Mutation Data Annotation Section](./mutation-data-transcript-annotation.md) for more details. To keep the old set + of default transcripts add the property `genomenexus.isoform_override_source=uniprot` + to [the properties file](https://docs.cbioportal.org/deployment/customization/portal.properties-reference/#properties). See the [v5.0.0 release notes](https://github.com/cBioPortal/cbioportal/releases/tag/v5.0.0) for more details. ## v3 -> v4 + - Introduces `logback` package for logging. If you don't have any custom log4j.properties file, no changes are necessary -- Cleans up several old databases ([PR](https://github.com/cBioPortal/cbioportal/pull/9360)). In theory the migration should be seamless, since the docker container detects an old database version and migrates it automatically. +- Cleans up several old databases ([PR](https://github.com/cBioPortal/cbioportal/pull/9360)). In theory the migration + should be seamless, since the docker container detects an old database version and migrates it automatically. See the [v4.0.0 release notes](https://github.com/cBioPortal/cbioportal/releases/tag/v4.0.0) for more details. ## v2 -> v3 -- Session service is now required to be set up. You can't run it without session service. The recommended way to run cBioPortal is to use the Docker Compose instructions. + +- Session service is now required to be set up. You can't run it without session service. The recommended way to run + cBioPortal is to use the Docker Compose instructions. ## v1 -> v2 -- Changes cBioPortal to a Single Page App (SPA) written in React, Mobx and bootstrap that uses a REST API. It shouldn't change anything for a deployer. + +- Changes cBioPortal to a Single Page App (SPA) written in React, Mobx and bootstrap that uses a REST API. It shouldn't + change anything for a deployer. diff --git a/docs/News-Genie.md b/docs/News-Genie.md index 05f50006c71..6d1b76da453 100644 --- a/docs/News-Genie.md +++ b/docs/News-Genie.md @@ -1,4 +1,8 @@ # Genie News +## May 1, 2023 +* **Public Release 13.1 of AACR Project GENIE:** + * The public release 13.1 version of AACR GENIE has 65 samples retracted that were present in AACR GENIE 13.0-public. + * More detailed information can be found in the [AACR GENIE release notes](https://www.synapse.org/#!Synapse:syn51355999) and the data releases page from [Sage Bionetworks](https://www.synapse.org/#!Synapse:syn7222066/wiki/410924) ## January 9, 2023 * **Public Release 13.0 of AACR Project GENIE:** * The first set of cancer genomic data aggregated through AACR Project Genomics Evidence Neoplasia Information Exchange (GENIE) was released to the global community in January 2017. The current release, GENIE 13.0-public now contains more than 167,000 sequenced samples from over 148,000 patients, making the AACR Project GENIE registry among the largest fully public cancer genomic data sets released to date. diff --git a/docs/News.md b/docs/News.md index 62902677a31..864d3058488 100644 --- a/docs/News.md +++ b/docs/News.md @@ -1,3 +1,65 @@ +## Aug 21, 2023 +* **Added data** consisting of 4,488 samples from 7 studies: + * [Lung Adenocarcinoma Met Organotropism (MSK, Cancer Cell 2023)](https://www.cbioportal.org/study/summary?id=luad_mskcc_2023_met_organotropism) *2653 samples* + * [Acute Myeloid Leukemia (OHSU, Cancer Cell 2022)](https://www.cbioportal.org/study/summary?id=aml_ohsu_2022) *942 samples* + * [Colon Cancer (Sidra-LUMC AC-ICAM, Nat Med 2023)](https://www.cbioportal.org/study/summary?id=coad_silu_2022) *348 samples* + * [Pediatric Neuroblastoma (MSK, Nat Genet 2023)](https://www.cbioportal.org/study/summary?id=nbl_msk_2023) *223 samples* + * [Colorectal Adenocarcinoma (MSK, Nat Commun 2022)](https://www.cbioportal.org/study/summary?id=bowel_colitis_msk_2022) *180 samples* + * [Bladder Cancer (Columbia University/MSK, Cell 2018)](https://www.cbioportal.org/study/summary?id=bladder_columbia_msk_2018) *130 samples* + * [Myoepithelial Carcinomas of Soft Tissue (WCM, CSH Molecular Case Studies 2022)](https://www.cbioportal.org/study/summary?id=stmyec_wcm_2022) *12 samples* + +* **Gene Tables Update** Updated tables of genes (main and alias), based on [Apr 1, 2023 HGNC release](http://ftp.ebi.ac.uk/pub/databases/genenames/hgnc/archive/monthly/tsv/). See seedDB release note [here](https://github.com/cBioPortal/datahub/tree/master/seedDB#latest-seed-database) for details. + +## Aug 1, 2023 +* **Enhancement**: One-sided Fisher's exact tests were changed to be two-sided. The affected pages are: + * Results View Page - Mutual Exclusivity Tab + * Results View Page - Comparison Tab - Genomic Alterations Tab + * Comparison Page - Genomic Alterations Tab + * Comparison Page - Mutations Tab + + Please note that the Mutations tab on the Comparison page is a recent feature and was introduced with the two-sided Fisher's exact test already implemented. + + Several users pointed out that using a one-sided test was incorrect for these comparisons. Please see discussions [here](https://github.com/cBioPortal/cbioportal/issues/9943) for more information. + +## May 2, 2023 +* **New Feature**: The mutations tab now shows variant annotations from the [repository of Variant with Unexpected Effects (reVUE)](https://www.cancerrevue.org/). + + +## Apr 11, 2023 +* **New Feature**: Disable autocommit and manually commit filters in study view. Manually commit filters can improve cBioPortal performance when query large dataset. + + + +## Apr 5, 2023 +* **Added data** consisting of 2,472 samples from 5 studies: + * [Bladder Cancer (MSK, Cell Reports 2022)](https://www.cbioportal.org/study/summary?id=paired_bladder_2022) *1659 samples* + * [Gastrointestinal Stromal Tumor (MSK, NPJ Precis Oncol 2023)](https://www.cbioportal.org/study/summary?id=gist_msk_2022) *499 samples* + * [Appendiceal Cancer (MSK, J Clin Oncol 2022)](https://www.cbioportal.org/study/summary?id=appendiceal_msk_2022) *273 samples* + * [Colorectal Cancer (MSK, Cancer Discovery 2022)](https://www.cbioportal.org/study/summary?id=coadread_mskresistance_2022) *22 samples* + * [Nerve Sheath Tumors (Johns Hopkins, Sci Data 2020)](https://www.cbioportal.org/study/summary?id=nst_nfosi_ntap) *19 samples* [**First GRCh38 Study**] + +* **Data Improvement** + * Added TERT promoter mutation status to [Melanomas (TCGA, Cell 2015)](https://www.cbioportal.org/study/summary?id=skcm_tcga_pub_2015), [Papillary Thyroid Carcinoma (TCGA, Cell 2014)](https://www.cbioportal.org/study/summary?id=thca_tcga_pub) TCGA studies. + +## Apr 4, 2023 +* **New Feature**: Allow numeric data type for custom data charts. + + + + This also allows to have numerical custom data after we query based on genes (custom data 2 in the image): + + + +## Jan 10, 2023 +* **New Feature**: New Pathways tab on the Group Comparison view. + [Example: Primary vs Metastasis samples in MSK-IMPACT Clinical Sequencing Cohort](https://www.cbioportal.org/comparison/pathways?comparisonId=61791fa92e3200072db9b64e&groupOrder=%5B%22Primary%22%2C%22Metastasis%22%5D) + + +## Dec 13, 2022 +* **New Feature**: New Mutations tab on the Group Comparison view. + [Example: Primary vs Metastasis samples in MSK-IMPACT Clinical Sequencing Cohort](https://www.cbioportal.org/comparison/mutations?comparisonId=61791fa92e3200072db9b64e&groupOrder=%5B%22Primary%22%2C%22Metastasis%22%5D) + + ## Oct 12, 2022 * **Added data** consisting of 1,459 samples from 10 studies: * [Hepatocellular Carcinoma (MERiC/Basel, Nat Commun. 2022)](https://www.cbioportal.org/study/summary?id=hcc_meric_2021) *122 samples* @@ -10,6 +72,13 @@ * [Mixed Tumors: Selpercatinib RET Trial (MSK, Nat Commun. 2022)](https://www.cbioportal.org/study/summary?id=mixed_selpercatinib_2020) *188 samples* * [Low-Grade Serous Ovarian Cancer (MSK, Clin Cancer Res 2022)](https://www.cbioportal.org/study/summary?id=lgsoc_mapk_msk_2022) *119 samples* * [Urothelial Carcinoma (BCAN/HCRN 2022)](http://www.cbioportal.org/study/summary?id=blca_bcan_hcrn_2022) *203 samples* + +## Sep 6, 2022 +* **Enhancement**: Oncoprint can now save clinical tracks after login + + +## Aug 11, 2022 +* **New Major Release**: **v5.0.0** release drops support for fusions in the mutation data format. Going forward fusions can only be imported in the Structural Variant (SV) format. This is mainly a refactoring effort to simplify the codebase and pave the way for the development of novel structural variant visualizations in the future. For cBioPortal instance maintainer, please reference our [Migration Guide](https://docs.cbioportal.org/migration-guide/#v4---v5) for instruction. ## Jul 26, 2022 * **Added data** consisting of 6,631 samples from 7 studies: @@ -21,6 +90,10 @@ * [Pan-cancer Analysis of Advanced and Metastatic Tumors (BCGSC, Nature Cancer 2020)](https://www.cbioportal.org/study/summary?id=pog570_bcgsc_2020) *570 samples* * [Prostate Adenocarcinoma (MSK, Clin Cancer Res. 2022)](https://www.cbioportal.org/study/summary?id=prad_pik3r1_msk_2021) *1,417 samples* +## May 31, 2022 +* **New Feature**: Added Quartiles, Median split and Generate bins options for bar charts on the study view page, where Generate bins allows user to define bin size and min value + + ## May 12, 2022 * **New Feature**: Show cohort alteration frequencies in pathways from [NDEx](https://www.ndexbio.org/iquery/) on the _Results View_. [Example: Glioblastoma signaling pathways in MSK-IMPACT (2017) cohort](https://bit.ly/3sE4UqD) @@ -413,9 +486,9 @@ * See more updates [here](https://github.com/cBioPortal/cbioportal/releases/tag/v3.1.8) ## December 12, 2019 -* **Enhancement**: Several enhancements to the display of gene panels on the _Patient View_ page, by [The Hyve](https://www.thehyve.nl/), described in more detail [here](https://blog.thehyve.nl/blog/gene-panels-patient-view) +* **Enhancement**: Several enhancements to the display of gene panels on the _Patient View_ page, by [The Hyve](https://www.thehyve.nl/), described in more detail [here](https://www.thehyve.nl/articles/gene-panels-cbioportal-patient-view) - ![image](https://blog.thehyve.nl/hubfs/gene-panels-patient-view-cbioportal.png) + ![image](https://api.thehyve.nl/uploads/gene-panels-patient-view-cbioportal.png) * **Enhancement**: Add Count Bubbles to Oncoprint Toolbar ![Screenshot from 2019-12-06 11-36-21](https://user-images.githubusercontent.com/20069833/70339336-aa16e700-181c-11ea-94ac-c4acff272e4f.png) @@ -431,9 +504,9 @@ ## November 22, 2019 -* **New Feature**: Support for Treatment response data in the Oncoprint and Plots tab, including new *Waterfall* plot type. Read more in [The Hyve's blog post](https://blog.thehyve.nl/blog/using-treatment-response-data-to-find-targeted-therapies-in-cbioportal) +* **New Feature**: Support for Treatment response data in the Oncoprint and Plots tab, including new *Waterfall* plot type. Read more in [The Hyve's blog post](https://www.thehyve.nl/articles/treatment-response-data-cbioportal) -![image](https://blog.thehyve.nl/hubfs/Waterfall%20plots%20cbioportal.png) +![image](https://api.thehyve.nl/uploads/Waterfall-plots-cbioportal.png) ## November 15, 2019 * **Enhancement**: heatmap tracks in OncoPrint now has separate headers and sub-menus. [example](https://www.cbioportal.org/results/oncoprint?Action=Submit&RPPA_SCORE_THRESHOLD=2.0&Z_SCORE_THRESHOLD=2.0&cancer_study_list=brca_tcga&case_set_id=brca_tcga_protein_quantification&clinicallist=PROFILED_IN_brca_tcga_mutations&data_priority=0&gene_list=ESR1%2520PGR%2520ERBB2&geneset_list=%20&genetic_profile_ids_PROFILE_COPY_NUMBER_ALTERATION=brca_tcga_gistic&genetic_profile_ids_PROFILE_MRNA_EXPRESSION=brca_tcga_mrna_median_Zscores&genetic_profile_ids_PROFILE_MUTATION_EXTENDED=brca_tcga_mutations&genetic_profile_ids_PROFILE_PROTEIN_EXPRESSION=brca_tcga_rppa_Zscores&heatmap_track_groups=brca_tcga_rna_seq_v2_mrna_median_Zscores%2CESR1%2CPGR%2CERBB2%3Bbrca_tcga_protein_quantification_zscores%2CESR1%2CPGR%2CERBB2&tab_index=tab_visualize) @@ -737,11 +810,9 @@ ## March 20, 2018 * The sixth phase of the cBioPortal architectural upgrade is now complete: The _Download_ tab has been moved to the new architecture. -* Data can now be downloaded in [tabular format](https://blog.thehyve.nl/blog/downloading-data-from-the-cbioportal-oncoprint-view) from OncoPrint. +* Data can now be downloaded in [tabular format](https://www.thehyve.nl/articles/download-data-from-cbioportal-oncoprint) from OncoPrint. * Added an option to download an SVG file on the _Cancer Type Summary_ tab. -![image](https://ptpb.pw/jMli.png) - ## January 15, 2018 * The fifth phase of the cBioPortal architectural upgrade is now complete: The OncoPrint and Survival tabs have been moved to the new architecture. diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 6398696496b..ed759c38b23 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -59,14 +59,15 @@ * [Updating your cBioPortal Database Scheme](Updating-your-cBioPortal-installation.md) * [Update genes and gene aliases](Updating-gene-and-gene_alias-tables.md) * [Migration Guide](Migration-Guide.md) -* [Development](documentation/docs/README.md) - * [Feature Development Guide](feature-development-guide.md) - * [cBioPortal Entity-relationship Diagram](cBioPortal-ER-Diagram.md) - * [cBioPortal Database Versioning](Database-Versioning.md) - * [Build cBioPortal with a different frontend version](Build-Different-Frontend.md) - * [Session Service](session-service-working.md) - * [Manual test cases](manual-test-cases.md) - * [Release Procedure](Release-Procedure.md) - * [Deployment Procedure](Deployment-Procedure.md) - * [This documentation site](Documentation-site.md) + * [MSK Maintenance](MSK-Maintenance.md) +* [Development](development/README.md) + * [Feature Development Guide](development/feature-development-guide.md) + * [cBioPortal Entity-relationship Diagram](development/cBioPortal-ER-Diagram.md) + * [cBioPortal Database Versioning](development/Database-Versioning.md) + * [Build cBioPortal with a different frontend version](development/Build-Different-Frontend.md) + * [Session Service](development/session-service-working.md) + * [Manual test cases](development/manual-test-cases.md) + * [Release Procedure](development/Release-Procedure.md) + * [Deployment Procedure](development/Deployment-Procedure.md) + * [This documentation site](development/Documentation-site.md) diff --git a/docs/Updating-your-cBioPortal-installation.md b/docs/Updating-your-cBioPortal-installation.md index 986f27475a6..011c7a39fa5 100644 --- a/docs/Updating-your-cBioPortal-installation.md +++ b/docs/Updating-your-cBioPortal-installation.md @@ -49,7 +49,7 @@ To run the migration script first go to the scripts folder `/core/src/main/scripts` and then run the following command: ```console -$ python migrate_db.py --properties-file /src/main/resources/portal.properties --sql /db-scripts/src/main/resources/migration.sql +$ python migrate_db.py ``` This should result in the following output: ```console diff --git a/docs/deployment/authorization-and-authentication/Authenticating-Users-via-Tokens.md b/docs/deployment/authorization-and-authentication/Authenticating-Users-via-Tokens.md index 9dde6968846..8925135b625 100644 --- a/docs/deployment/authorization-and-authentication/Authenticating-Users-via-Tokens.md +++ b/docs/deployment/authorization-and-authentication/Authenticating-Users-via-Tokens.md @@ -45,6 +45,12 @@ The following properties must be present in portal.properties in order to allow * **Permissible Values**: jwt, uuid, oauth2, none * **Default Value**: none +**Property**: dat.filter\_user\_role (optional) + +* **Description**: This property determines users access in token generation. If present, this role will be checked in user roles before generating a token. +* **Permissible Values**: A string value. +* **Default Value**: none + **Property**: dat.unauth\_users (optional, not used for dat.method = oauth2) * **Description**: A list of users that should not be allowed to download a data access token. diff --git a/docs/deployment/authorization-and-authentication/Authenticating-and-Authorizing-Users-via-keycloak.md b/docs/deployment/authorization-and-authentication/Authenticating-and-Authorizing-Users-via-keycloak.md index a7e9e19e8a8..74cc3671e7e 100644 --- a/docs/deployment/authorization-and-authentication/Authenticating-and-Authorizing-Users-via-keycloak.md +++ b/docs/deployment/authorization-and-authentication/Authenticating-and-Authorizing-Users-via-keycloak.md @@ -1,5 +1,7 @@ # Authenticating and Authorizing Users via Keycloak +**⚠️ This documentation is for keycloak . +Please note that configuring your local instance to use Keycloak authentication requires a Keycloak server to be set up. For details on how to set up a Keycloak server, please read online document at . This document focuses mainly on the steps to configure Keycloak for **authenticating** cBioPortal users. @@ -15,7 +17,7 @@ To skip to the authorization section see: [authorization with Keycloak](#authori ### Why Keycloak? -Keycloak is an [open source identity and access management solution](https://keycloak.gitbooks.io/documentation/server_admin/topics/overview.html). It has a built-in RDBM system to store login information. It can help build a security layer on top of the cBioPortal web application. +Keycloak is an [open source identity and access management solution](https://www.keycloak.org/docs/latest/server_admin/index.html). It has a built-in RDBM system to store login information. It can help build a security layer on top of the cBioPortal web application. Keycloak boils down to three simple terms: * **realm**: A realm secures and manages security metadata for a set of users, application, and registered auth clients. @@ -156,9 +158,9 @@ cBioPortal, deciding which authorities to grant when telling cBioPortal that the user has authenticated. Please refer to the Keycloak documentation on -[user federation](https://keycloak.gitbooks.io/documentation/server_admin/topics/user-federation.html) +[user federation](https://www.keycloak.org/docs/latest/server_admin/index.html#_user-storage-federation) and -[identity brokering](https://keycloak.gitbooks.io/documentation/server_admin/topics/identity-broker.html) +[identity brokering](https://www.keycloak.org/docs/latest/server_admin/index.html#_identity_broker) for more information on how to integrate Keycloak with your local LDAP or SAML service. diff --git a/docs/deployment/customization/Customizing-your-instance-of-cBioPortal.md b/docs/deployment/customization/Customizing-your-instance-of-cBioPortal.md index ce40b8fcfc9..1f389f4159d 100644 --- a/docs/deployment/customization/Customizing-your-instance-of-cBioPortal.md +++ b/docs/deployment/customization/Customizing-your-instance-of-cBioPortal.md @@ -145,6 +145,12 @@ Below you can find the complete list of all the available skin properties. Text for public cBioPortal.org. Any HTML text + + skin.right_nav.show_web_tours + set the "Interactive Tours" section in the right navigation bar + true + true / false + skin.show_about_tab show the "ABOUT" tab in the header @@ -243,9 +249,16 @@ Below you can find the complete list of all the available skin properties. skin.hide_download_controls - removes all download and copy-to-clipboard options. + controls download options in UI. **true**: hides all download options. **false**: shows all download options. **data**: disable data download but not figure download false - true / false + true / false / data + + + download_group + controls download options in UI for each user. If present and user is authenticated, this value is checked against user roles. +If the download_group is present in user groups then download options are shown in UI, else it fallback to **skin.hide_download_controls** + + text skin.show_settings_menu diff --git a/docs/deployment/customization/Studyview.md b/docs/deployment/customization/Studyview.md index 6dec966816b..3f86d4b8a1e 100644 --- a/docs/deployment/customization/Studyview.md +++ b/docs/deployment/customization/Studyview.md @@ -25,6 +25,8 @@ The higher the score, the higher priority it will be displayed in the study view If you want to hide chart, please set the priority to 0. For combination chart, as long as one of the clinical attributes has been set to 0, it will be hidden. +To disable the chart, set the priority to -1.(Currently disables charts for single clinical attributes only) + Currently, we preassigned priority to few charts, but as long as you assign a priority in the database except than 1, these preassigned priorities will be overwritten. | Chart name(clinical attribute ID) | Frontend default priority | Additional Info | diff --git a/docs/deployment/customization/portal.properties-Reference.md b/docs/deployment/customization/portal.properties-Reference.md index 48aec8946d2..bff32c60fb6 100644 --- a/docs/deployment/customization/portal.properties-Reference.md +++ b/docs/deployment/customization/portal.properties-Reference.md @@ -7,18 +7,25 @@ This page describes the main properties within portal.properties. ``` db.user= db.password= -db.host=[e.g. localhost to connect via socket, or e.g. 127.0.0.1:3307 to connect to a different port like 3307. Used by Java data import layer] -db.portal_db_name=[the database name in mysql, e.g. cbiodb] +db.connection_string= db.driver=[this is the name of your JDBC driver, e.g., com.mysql.jdbc.Driver] ``` -Include `db_connection_string` with the format specified below, and replace `localhost` by the value of `db.host`: +The format of the `db.connection_string` is: +``` +jdbc:mysql://:/?&& +``` + +For example: ``` -db.connection_string=jdbc:mysql://localhost/ +jdbc:mysql://localhost:3306/cbiodb?zeroDateTimeBehavior=convertToNull&useSSL=false ``` -db.tomcat\_resource\_name is required in order to work with the tomcat database connection pool and should have the default value jdbc/cbioportal in order to work correctly with the your WAR file. +:warning: The fields `db.host` and `db.portal_db_name` and `db.use_ssl` are deprecated. It is required to configure the database connection using +the `db.connection_string` instead. + +`db.tomcat_resource_name` is required in order to work with the tomcat database connection pool and should have the default value jdbc/cbioportal in order to work correctly with the your WAR file. ``` db.tomcat_resource_name=jdbc/cbioportal @@ -100,6 +107,9 @@ skin.right_nav.show_whats_new= skin.right_nav.show_twitter= ``` +#Interactive tours section +skin.right_nav.show_web_tours= + ### Control the content of specific sections Setting controlling the blurb: you can add any HTML code here that you want to visualize. This will be shown between the cBioPortal menu and the Query selector in the main page. @@ -153,6 +163,13 @@ Different samples of a patient may have been analyzed with different gene panels skin.patientview.filter_genes_profiled_all_samples= ``` +### Control default settings of the VAF line chart in the genomic evolution tab of patient view +If you want to enable log scale and sequential mode by default, set this property to `true`: +``` +vaf.log_scale.default=true|false +vaf.sequential_mode.default=true|false +``` + ### Control unauthorized studies to be displayed on the home page By default, on an authenticated portal the home page will only show studies for which the current user is authorized. By setting the _skin.home\_page.show\_unauthorized\_studies_ property to _true_ the home page will also show unauthorized studies. The unauthorized studies will appear greyed out and cannot be selected for downstream analysis in Results View or Study View. @@ -167,6 +184,13 @@ If _show\_unauthorized\_studies_ feature has been enabled, a message (template) skin.home_page.unauthorized_studies_global_message= ``` +### Show badge with reference genome +In instances with hg19 and hg38 studies you can show the reference genome in the home page next to the number of samples. This can be done setting this property to `true` (`false` by default): + +``` +skin.home_page.show_reference_genome= +``` + ### Control the appearance of the settings menu in study view and group comparison that controls custom annotation-based filtering A settings menu that allows the user to filter alterations in study view and group comparison may be used when [custom driver annotations](/File-Formats.md#custom-driver-annotations) were loaded for the study or studies displayed in these sections. This menu will only appear, when setting the property _skin.show\_settings\_menu_ to _true_. @@ -201,6 +225,19 @@ skin.patient_view.copy_number_table.columns.show_on_init= skin.patient_view.structural_variant_table.columns.show_on_init= ``` +### Define custom sample type colors +Define the colors of custom sample types in the patient view using a json object with for each sample type a color: +``` +skin.patient_view.custom_sample_type_colors_json=classpath:/skin-patient-view-custom-sample-type-colors.json +``` +Example of json file contents: +```json +{ + "Primary": "green", + "Biopsy 3": "#00c040ff" +} +``` + ### Choose the display name for authenticated users By default the display name for authenticated users is email, but it can be changed for the user name: @@ -429,6 +466,11 @@ oncoprint.oncokb.default=true|false oncoprint.hotspots.default=true|false ``` +If you want to enable oncoprint heatmap clustering by default, set this property to `true`: +``` +oncoprint.clustered.default=true|false +``` + **Automatic hiding of variants of unknown significance (VUS)** By default, the selection box to hide VUS mutations is unchecked. If you want to automatically hide VUS, set this property to `true`. Default is `false`. @@ -627,6 +669,39 @@ By default, the tree is expanded (property value is `false`). skin.geneset_hierarchy.collapse_by_default = true ``` +## Cross study expression and protein data + + +By default we hide expression data for multi-study queries as they are +usually not normalized across studies. For the public cBioPortal for instance, only TCGA Pancan Atlas studies expression data has been normalized. + +If you know the expression data in your instance is comparable, or is comparable for a subset of +studies, you can configure a rule as follows. + +The value of this property can be boolean (true|false) or a javascript function +which executes at runtime and is passed the list of study objects being queried +by the user and evaluates whether expression data can be safely displayed. + +``` +// a function that accepts the users's selected studies and +// returns whether or not to allow expression data from the involved studies to be mixed +enable_cross_study_expression = (selectedStudies)=>{ [your logic] return true|false } +``` + +``` +// boolean +enable_cross_study_expression = true|false +``` + +## Combined Study View Summary Limits +### Background +A limit is added to prevent poor performance of Study View when selecting too large sample numbers. +### Properties +* `studyview.max_samples_selected`: Limit is disabled when not set + +### Behavior +When these limits are exceeded the "Explore Selected Studies" button will be disabled on the Study View Page. + ## Request Body Compression ### Background @@ -663,3 +738,21 @@ There are two `portal.property` values related to this feature: * This is not a cure-all for performance issues * Most requests the cBioPortal makes do not have large request bodies, so most requests will not be compressed, and will see no performance improvement. * Users with good upload speeds will see minimal performance improvements, as their upload speed is not a bottleneck. + +# DataSets Tab (Study Download Links) +### Background +The DataSets tab has the ability to create a ``download`` button that allows users to quickly download "raw" public studies. +### Properties +* ``study_download_url`` : when set, the feature will be enabled +### Behavior +For private instances that want to replicate the``public-portal`` they first must set up their studies +they want available for download in a similar format to what is described in the Example section below. +The studies are located on the ``public-portal`` at `https://cbioportal-datahub.s3.amazonaws.com/`. +Then there is a ``study_list.json`` defined that list the studies that can be downloaded. +The studies to be downloaded need to be compressed with the extension ``tar.gz`` + +### Example +* We have set ``study_download_url`` property to `https://cbioportal-datahub.s3.amazonaws.com/` +* ``study_list.json`` resides ``https://cbioportal-datahub.s3.amazonaws.com/study_list.json`` + * ``[ "acbc_mskcc_2015", "acc_2019"]`` Example of contents +* ``acbc_mskcc_2015.tar.gz`` resides `https://cbioportal-datahub.s3.amazonaws.com/acbc_mskcc_2015.tar.gz` diff --git a/docs/deployment/deploy-without-docker/Software-Requirements.md b/docs/deployment/deploy-without-docker/Software-Requirements.md index 75b59ab1fea..d6b2fed8815 100644 --- a/docs/deployment/deploy-without-docker/Software-Requirements.md +++ b/docs/deployment/deploy-without-docker/Software-Requirements.md @@ -16,7 +16,7 @@ The session service uses MongoDB 3.6.6 ## Java -As of this writing, the cBioPortal can be compiled and run from Java 8.0 and above. The software can be found and download from the [Oracle](https://www.oracle.com/us/technologies/java/overview/index.html) website. +As of this writing, the cBioPortal can be compiled and run from Java 11 and above. The software can be found and download from the [Oracle](https://www.oracle.com/us/technologies/java/overview/index.html) website. On Ubuntu: ```sudo apt-get install default-jdk``` diff --git a/docs/deployment/docker/README.md b/docs/deployment/docker/README.md index 15a37fc7742..384b27423f4 100644 --- a/docs/deployment/docker/README.md +++ b/docs/deployment/docker/README.md @@ -18,7 +18,7 @@ In this example we use [Docker Compose](https://docs.docker.com/compose/) to spi git clone https://github.com/cBioPortal/cbioportal-docker-compose.git cd cbioportal-docker-compose ./init.sh -docker-compose up +docker compose up ``` You should now be able to see the cBioPortal website at http://localhost:8080 @@ -26,7 +26,7 @@ You should now be able to see the cBioPortal website at http://localhost:8080 Import studies with: ``` -docker-compose run cbioportal metaImport.py -u http://cbioportal:8080 -s study/lgg_ucsf_2014/ -o +docker compose run cbioportal metaImport.py -u http://cbioportal:8080 -s study/lgg_ucsf_2014/ -o ``` Clear persistent data volumes with: @@ -54,7 +54,7 @@ Then download all necessary files (seed data, example config and example study f Then run: ``` -docker-compose up +docker compose up ``` This will start all four containers (services) defined [here](https://github.com/cBioPortal/cbioportal-docker-compose/blob/master/docker-compose.yml). That is: @@ -76,7 +76,7 @@ Go to the next step to see how to import studies. If you prefer to run the services in detached mode (i.e. not logging everything to your terminal), you can run ``` -docker-compose up -d +docker compose up -d ``` In this mode, you'll have to check the logs of each container manually using e.g.: @@ -95,12 +95,12 @@ docker ps -a To import studies you can run: ``` -docker-compose run cbioportal metaImport.py -u http://cbioportal:8080 -s study/lgg_ucsf_2014/ -o +docker compose run cbioportal metaImport.py -u http://cbioportal:8080 -s study/lgg_ucsf_2014/ -o ``` This will import the [lgg_ucsf_2014 study](https://www.cbioportal.org/patient?studyId=lgg_ucsf_2014) into your local database. It will take a few minutes to import. After importing, restart the cbioportal web container: ``` -docker-compose restart cbioportal +docker compose restart cbioportal ``` or diff --git a/docs/deployment/docker/example_commands.md b/docs/deployment/docker/example_commands.md index 38040e480de..f9f26f56009 100644 --- a/docs/deployment/docker/example_commands.md +++ b/docs/deployment/docker/example_commands.md @@ -7,7 +7,7 @@ gene panel files in `./study` which is mounted inside the container on `/study/. ```shell docker-compose run \ -v :/gene_panels/gene_panel.txt:ro \ - cbioportal + cbioportal \ bash -c 'cd /cbioportal/core/src/main/scripts/ && ./importGenePanel.pl --data /gene_panels/gene_panel.txt' ``` diff --git a/docs/Build-Different-Frontend.md b/docs/development/Build-Different-Frontend.md similarity index 100% rename from docs/Build-Different-Frontend.md rename to docs/development/Build-Different-Frontend.md diff --git a/docs/Database-Versioning.md b/docs/development/Database-Versioning.md similarity index 100% rename from docs/Database-Versioning.md rename to docs/development/Database-Versioning.md diff --git a/docs/Deployment-Procedure.md b/docs/development/Deployment-Procedure.md similarity index 100% rename from docs/Deployment-Procedure.md rename to docs/development/Deployment-Procedure.md diff --git a/docs/Documentation-site.md b/docs/development/Documentation-site.md similarity index 74% rename from docs/Documentation-site.md rename to docs/development/Documentation-site.md index 10248e83377..0b7a7401009 100644 --- a/docs/Documentation-site.md +++ b/docs/development/Documentation-site.md @@ -1,6 +1,6 @@ # Documentation site -This documentation site is created using [https://retype.com/](), a static site generator based on markdown. +This documentation site is created using [https://retype.com/](https://retype.com/), a static site generator based on markdown. Visit their site for installation instructions and a guide on how diff --git a/docs/docs/README.md b/docs/development/README.md similarity index 87% rename from docs/docs/README.md rename to docs/development/README.md index f15639569ad..4b87d00b1e1 100644 --- a/docs/docs/README.md +++ b/docs/development/README.md @@ -12,4 +12,4 @@ Note that cBioPortal is split into a backend project (api) and a frontend projec - [Backend](http://www.github.com/cbioportal/cbioportal) (Java, Spring, MySQL, MongoDB) -If you are interested in coordinating the development of new features, please contact cbioportal@cbio.mskcc.org or reach out on https://slack.cbioportal.org. \ No newline at end of file +If you are interested in coordinating the development of new features, please contact cbioportal@cbioportal.org or reach out on https://slack.cbioportal.org. diff --git a/docs/Release-Procedure.md b/docs/development/Release-Procedure.md similarity index 96% rename from docs/Release-Procedure.md rename to docs/development/Release-Procedure.md index 9259b815873..cec9d32f48a 100644 --- a/docs/Release-Procedure.md +++ b/docs/development/Release-Procedure.md @@ -38,7 +38,7 @@ For releases with database migrations, we increase the MINOR number in MAJOR.MIN ### From pre-release to official release -On the [GitHub Release Page](https://github.com/cBioPortal/cbioportal/releases) you will see that some releases have the pre-release indication whereas others do not. In general we make a new pre-release release every week. We test it out in production (https://cbioportal.org) for one week and if no new critical issues are identified we make it an official release. +On the [GitHub Release Page](https://github.com/cBioPortal/cbioportal/releases) you will see that some releases have the pre-release indication whereas others do not. In general we make a new pre-release release every week. We test it out in production (https://cbioportal.org) for one month and if no new critical issues are identified we make it an official release. Occasionally we make a new official release in less than a month's time if we identify a critical issue in the previous release. ### cBioPortal Software Version Numbers diff --git a/docs/cBioPortal-ER-Diagram.md b/docs/development/cBioPortal-ER-Diagram.md similarity index 100% rename from docs/cBioPortal-ER-Diagram.md rename to docs/development/cBioPortal-ER-Diagram.md diff --git a/docs/feature-development-guide.md b/docs/development/feature-development-guide.md similarity index 100% rename from docs/feature-development-guide.md rename to docs/development/feature-development-guide.md diff --git a/docs/manual-test-cases.md b/docs/development/manual-test-cases.md similarity index 100% rename from docs/manual-test-cases.md rename to docs/development/manual-test-cases.md diff --git a/docs/session-service-working.md b/docs/development/session-service-working.md similarity index 100% rename from docs/session-service-working.md rename to docs/development/session-service-working.md diff --git a/docs/user-guide/faq.md b/docs/user-guide/faq.md index c59bcd1bf68..ea7d3d653e0 100644 --- a/docs/user-guide/faq.md +++ b/docs/user-guide/faq.md @@ -20,6 +20,7 @@ * [What is a Virtual Study?](/user-guide/faq.md#what-is-a-virtual-study) * [Is it necessary to log in to use virtual studies? If I do log in, what additional functionality do I gain?](/user-guide/faq.md#is-it-necessary-to-log-in-to-use-virtual-studies-if-i-do-log-in-what-additional-functionality-do-i-gain) * [What is Group Comparison?](/user-guide/faq.md#what-is-group-comparison) + * [What are the statistical significance tests in Group Comparison?](/user-guide/faq.md#what-are-the-statistical-significance-tests-in-group-comparison) * [Data Questions](/user-guide/faq.md#data-questions) * [General Data](/user-guide/faq.md#general-data) * [Does the portal contain cancer study X?](/user-guide/faq.md#does-the-portal-contain-cancer-study-x) @@ -137,7 +138,18 @@ No. A user that has not logged in can create virtual studies and run queries in If you log in, you gain the ability to save your virtual study to the list of existing studies on the homepage. This makes a virtual study functionally the same as any other study: you can access your virtual studies in the query builder and you can combine an existing virtual study with any other study to create a new virtual study. #### What is Group Comparison? Group Comparison is a suite of analysis features which allows a user to compare clinical or genomic features of user-defined groups of samples. These groups can be defined based on any clinical or genomic features. For an overview, see [our tutorial on group comparison](https://www.cbioportal.org/tutorials). - +#### What are the statistical significance tests in Group Comparison? +- Survival tab: Log-rank test +- Clinical tab: + - Continuous data: Chi-squared test + - Categorical data: Kruskal Wallis test +- Other tabs + - 2 groups + - Continuous data: one-sided t-test + - Categorical data: two-sided Fisher's exact test + - 3 or more groups + - Continuous data: one-way ANOVA + - Categorical data: Chi-squared test ## Data Questions ### General Data diff --git a/docs/user-guide/overview.md b/docs/user-guide/overview.md index f217104e13b..ae18a16339e 100644 --- a/docs/user-guide/overview.md +++ b/docs/user-guide/overview.md @@ -28,6 +28,7 @@ Short videos that show how to perform specific analyses or how to use specific p 6. How to explore the data in a study [youtube.com](https://www.youtube.com/watch?v=N8ffDgkqDWc) 7. How to run a query for genes of interest [youtube.com](https://www.youtube.com/watch?v=MH-kY5usA70) 8. How to download data [youtube.com](https://www.youtube.com/watch?v=JId304dp3tc) +9. Navigating AACR GENIE - Biopharma Collaborative (BPC) dataset [youtube.com](https://www.youtube.com/playlist?list=PLE2tjlUyHL8Gn4ythnuvf2BxWJVpAxkMM) ### Documentation * Frequently Asked Questions [FAQ](/user-guide/faq.md) @@ -37,3 +38,7 @@ Short videos that show how to perform specific analyses or how to use specific p * Cerami et al. Cancer Discovery 2012 [PubMed](http://cancerdiscovery.aacrjournals.org/content/2/5/401.abstract) * Gao et al. Science Signaling 2013 [PubMed](https://www.ncbi.nlm.nih.gov/pubmed/23550210) +### Tutorials by others +* cBioPortal Tutorial Series by Jackson Laboratory [youtube.com](https://www.youtube.com/watch?v=tWdrcZOiXc0&list=PLWNp6Z5dXDZ7yRyny8aypSwrArs6e0EJi) +* Using the Cancer Digital Slide Archive in cBioPortal by Nicole M. Rivera Acevedo [youtube.com (English)](https://www.youtube.com/watch?v=oP0GbWmfVWM) | [youtube.com (Spanish)](https://www.youtube.com/watch?v=QyOVCxjVIPU) +* Visualizing and Downloading RNASeq data from cBioPortal by Farhan Haq [youtube.com](https://www.youtube.com/watch?v=I3KiLCE35Mk&list=PLvK49Q0ARs91Ilonq_07n0q9Cd5pOsdJW) diff --git a/docs/web-API-and-Clients.md b/docs/web-API-and-Clients.md index a6c8081344d..762f0da3649 100644 --- a/docs/web-API-and-Clients.md +++ b/docs/web-API-and-Clients.md @@ -8,9 +8,9 @@ Please see the full reference documentation for the API [here](https://www.cbiop The cBioPortal REST API is described using Swagger/OpenAPI, which allows one to generate a client in most programming languages. One can use the command line tool `curl` for dowloading data on the command line or use another language such as `Python` or `R` to make visualizations. We list some common examples below, but if your language is not listed, there is likely a client generator available elsewhere (see e.g. https://swagger.io/tools/swagger-codegen/). Do reach out if you'd like us to add a language. -### R client +### R clients -There are multiple ways to access the API using R. The recommended way is to use `cBioPortalData`. +There are multiple ways to access the API using R. Below are two recommended R packages to access cBioPortal data. #### cBioPortalData (recommended) @@ -34,9 +34,22 @@ cBioPortal( ) ``` +#### cbioportalR (recommended) + +cbioportalR offers easy-to-use functions that allow users to browse and pull data from public or institutional cBioPortal sites without knowledge of web service or Bioconductor infrastructures. The package is tidyverse-compatible. Key package features include: + +1. Comprehensive documentation aimed at helping clinical researchers understand the underlying structure of cBioPortal data +2. [Tutorials]([https://www.karissawhiting.com/cbioportalR/articles/overview-of-workflow.html]) for quick API authentication and set up +3. Functions to pull complete clinical and genomic data by study ID, molecular profile ID, sample list IDs or individual sample ID (e.g. `get_genetics_by_study()`, `get_genetics_by_sample()`) +4. Functions to navigate and identify patient IDs, sample IDs or study IDs as needed, or infer necessary ID information for queries when not supplied by user. +5. Helper functions to pull information on gene panels (`get_gene_panel()`), or lookup entrez ID (`get_entrez_id()`), Hugo Symbol (`get_hugo_symbol()`) or common gene aliases (`get_alias()`) of genes +6. Capability to query multiple sample IDs from different studies concurrently + +For a detailed tutorial on `cbioportalR`, see the package website: https://www.karissawhiting.com/cbioportalR/articles/overview-of-workflow.html + #### rapiclient -Although we recommend to use [cBioPortalData](/#cbioportaldata-recommended) for most use cases, it is possible to connect to the API directly using [rapiclient](https://github.com/bergant/rapiclient): +Although we recommend [cBioPortalData](/#cbioportaldata-recommended) or [cbioportalR](/#cbioportalR-recommended) for most use cases, it is possible to connect to the API directly using [rapiclient](https://github.com/bergant/rapiclient): ``` library(rapiclient) diff --git a/maf/src/main/java/org/mskcc/cbio/maf/MafRecord.java b/maf/src/main/java/org/mskcc/cbio/maf/MafRecord.java index 512372e642c..673faf0cd3a 100644 --- a/maf/src/main/java/org/mskcc/cbio/maf/MafRecord.java +++ b/maf/src/main/java/org/mskcc/cbio/maf/MafRecord.java @@ -103,16 +103,14 @@ public class MafRecord { private String maLinkMsa; private String maLinkPdb; - // Oncotator cols - private String oncotatorDbSnpRs; - private String oncotatorDbSnpValStatus; - private String oncotatorVariantClassification; - private String oncotatorRefseqMrnaId; - private String oncotatorUniprotName; - private String oncotatorUniprotAccession; - private String oncotatorCodonChange; - private int oncotatorProteinPosStart; - private int oncotatorProteinPosEnd; + // Oncotator columns are renamed to maf columns + private String mafDbSnpValStatus; + private String mafVariantClassification; + private String mafRefseqMrnaId; + private String mafUniprotAccession; + private String mafCodonChange; + private int mafProteinPosStart; + private int mafProteinPosEnd; // custom filtering of passenger and driver mutations cols private String driverFilter; @@ -521,76 +519,60 @@ public void setProteinPosition(String proteinPosition) { this.proteinPosition = proteinPosition; } - public String getOncotatorVariantClassification() { - return oncotatorVariantClassification; + public String getMafVariantClassification() { + return mafVariantClassification; } - public void setOncotatorVariantClassification(String oncotatorVariantClassification) { - this.oncotatorVariantClassification = oncotatorVariantClassification; + public void setMafVariantClassification(String mafVariantClassification) { + this.mafVariantClassification = mafVariantClassification; } - - public String getOncotatorDbSnpRs() { - return oncotatorDbSnpRs; - } - - public void setOncotatorDbSnpRs(String oncotatorDbSnpRs) { - this.oncotatorDbSnpRs = oncotatorDbSnpRs; - } - - public String getOncotatorDbSnpValStatus() { - return oncotatorDbSnpValStatus; - } - - public void setOncotatorDbSnpValStatus(String oncotatorDbSnpValStatus) { - this.oncotatorDbSnpValStatus = oncotatorDbSnpValStatus; - } - - public String getOncotatorRefseqMrnaId() { - return oncotatorRefseqMrnaId; + + public String getMafDbSnpValStatus() { + return mafDbSnpValStatus; } - public void setOncotatorRefseqMrnaId(String oncotatorRefseqMrnaId) { - this.oncotatorRefseqMrnaId = oncotatorRefseqMrnaId; + public void setMafDbSnpValStatus(String mafDbSnpValStatus) { + this.mafDbSnpValStatus = mafDbSnpValStatus; } - public String getOncotatorUniprotName() { - return oncotatorUniprotName; + public String getMafRefseqMrnaId() { + return mafRefseqMrnaId; } - public void setOncotatorUniprotName(String oncotatorUniprotName) { - this.oncotatorUniprotName = oncotatorUniprotName; + public void setMafRefseqMrnaId(String mafRefseqMrnaId) { + this.mafRefseqMrnaId = mafRefseqMrnaId; } - public String getOncotatorUniprotAccession() { - return oncotatorUniprotAccession; + public String getMafUniprotAccession() { + return mafUniprotAccession; } - public void setOncotatorUniprotAccession(String oncotatorUniprotAccession) { - this.oncotatorUniprotAccession = oncotatorUniprotAccession; + public void setMafUniprotAccession(String mafUniprotAccession) { + this.mafUniprotAccession = mafUniprotAccession; } - public String getOncotatorCodonChange() { - return oncotatorCodonChange; + public String getMafCodonChange() { + return mafCodonChange; } - public void setOncotatorCodonChange(String oncotatorCodonChange) { - this.oncotatorCodonChange = oncotatorCodonChange; + public void setMafCodonChange(String mafCodonChange) { + this.mafCodonChange = mafCodonChange; } - public int getOncotatorProteinPosStart() { - return oncotatorProteinPosStart; + public int getMafProteinPosStart() { + return mafProteinPosStart; } - public void setOncotatorProteinPosStart(int oncotatorProteinPosStart) { - this.oncotatorProteinPosStart = oncotatorProteinPosStart; + public void setMafProteinPosStart(int mafProteinPosStart) { + this.mafProteinPosStart = mafProteinPosStart; } - public int getOncotatorProteinPosEnd() { - return oncotatorProteinPosEnd; + public int getMafProteinPosEnd() { + return mafProteinPosEnd; } - public void setOncotatorProteinPosEnd(int oncotatorProteinPosEnd) { - this.oncotatorProteinPosEnd = oncotatorProteinPosEnd; + public void setMafProteinPosEnd(int mafProteinPosEnd) { + this.mafProteinPosEnd = mafProteinPosEnd; } public String getMaFuncImpact() { diff --git a/maf/src/main/java/org/mskcc/cbio/maf/MafUtil.java b/maf/src/main/java/org/mskcc/cbio/maf/MafUtil.java index 144041ed7e8..356ecbf470f 100644 --- a/maf/src/main/java/org/mskcc/cbio/maf/MafUtil.java +++ b/maf/src/main/java/org/mskcc/cbio/maf/MafUtil.java @@ -110,22 +110,13 @@ public class MafUtil { public static final String PROTEIN_POSITION = "Protein_position"; // oncotator column names - public static final String ONCOTATOR_DBSNP_RS = "ONCOTATOR_DBSNP_RS"; public static final String ONCOTATOR_VARIANT_CLASSIFICATION = "ONCOTATOR_VARIANT_CLASSIFICATION"; public static final String ONCOTATOR_REFSEQ_MRNA_ID = "ONCOTATOR_REFSEQ_MRNA_ID"; - public static final String ONCOTATOR_UNIPROT_ENTRY_NAME = "ONCOTATOR_UNIPROT_ENTRY_NAME"; public static final String ONCOTATOR_UNIPROT_ACCESSION = "ONCOTATOR_UNIPROT_ACCESSION"; public static final String ONCOTATOR_CODON_CHANGE = "ONCOTATOR_CODON_CHANGE"; public static final String ONCOTATOR_PROTEIN_POS_START = "ONCOTATOR_PROTEIN_POS_START"; public static final String ONCOTATOR_PROTEIN_POS_END = "ONCOTATOR_PROTEIN_POS_END"; - - // mutation assessor column names - public static final String MA_FIMPACT = "MA:FImpact"; - public static final String MA_FIS = "MA:FIS"; - public static final String MA_LINK_VAR = "MA:link.var"; - public static final String MA_LINK_MSA = "MA:link.MSA"; - public static final String MA_LINK_PDB = "MA:link.PDB"; - + // custom filtering of passenger and driver mutations column names public static final String DRIVER_FILTER = "cbp_driver"; public static final String DRIVER_FILTER_ANNOTATION = "cbp_driver_annotation"; @@ -182,10 +173,8 @@ public class MafUtil { private int normalVafIndex = -1; // default Oncotator column indices - private int oncoDbSnpRsIndex = -1; private int oncoVariantClassificationIndex = -1; private int oncoRefseqMrnaIdIndex = -1; - private int oncoUniprotNameIndex = -1; private int oncoUniprotAccessionIndex = -1; private int oncoCodonChangeIndex = -1; private int oncoProteinPosStartIndex = -1; @@ -304,14 +293,10 @@ public MafUtil(String headerLine, Set namespaces) { scoreIndex = i; } else if(header.equalsIgnoreCase(BAM_FILE)) { bamFileIndex = i; - } else if(header.equalsIgnoreCase(ONCOTATOR_DBSNP_RS)) { - oncoDbSnpRsIndex = i; } else if(header.equalsIgnoreCase(ONCOTATOR_VARIANT_CLASSIFICATION)) { oncoVariantClassificationIndex = i; } else if(header.equalsIgnoreCase(ONCOTATOR_REFSEQ_MRNA_ID)) { oncoRefseqMrnaIdIndex = i; - } else if(header.equalsIgnoreCase(ONCOTATOR_UNIPROT_ENTRY_NAME)) { - oncoUniprotNameIndex = i; } else if(header.equalsIgnoreCase(ONCOTATOR_UNIPROT_ACCESSION)) { oncoUniprotAccessionIndex = i; } else if(header.equalsIgnoreCase(ONCOTATOR_CODON_CHANGE)) { @@ -320,16 +305,6 @@ public MafUtil(String headerLine, Set namespaces) { oncoProteinPosStartIndex = i; } else if(header.equalsIgnoreCase(ONCOTATOR_PROTEIN_POS_END)) { oncoProteinPosEndIndex = i; - } else if(header.equalsIgnoreCase(MA_FIMPACT)) { - maFImpactIndex = i; - } else if(header.equalsIgnoreCase(MA_FIS)) { - maFisIndex = i; - } else if(header.equalsIgnoreCase(MA_LINK_VAR)) { - maLinkVarIndex = i; - } else if(header.equalsIgnoreCase(MA_LINK_MSA)) { - maLinkMsaIndex = i; - } else if(header.equalsIgnoreCase(MA_LINK_PDB)) { - maLinkPdbIndex = i; } else if(header.equalsIgnoreCase(T_REF_COUNT) || header.equalsIgnoreCase(I_T_REF_COUNT) || header.equalsIgnoreCase(AD_REF)) { @@ -446,14 +421,12 @@ public MafRecord parseRecord(String line) { record.setMaLinkPdb(TabDelimitedFileUtil.getPartString(maLinkPdbIndex, parts)); // Oncotator columns - record.setOncotatorDbSnpRs(TabDelimitedFileUtil.getPartString(oncoDbSnpRsIndex, parts)); - record.setOncotatorVariantClassification(TabDelimitedFileUtil.getPartString(oncoVariantClassificationIndex, parts)); - record.setOncotatorRefseqMrnaId(TabDelimitedFileUtil.getPartString(oncoRefseqMrnaIdIndex, parts)); - record.setOncotatorUniprotName(TabDelimitedFileUtil.getPartString(oncoUniprotNameIndex, parts)); - record.setOncotatorUniprotAccession(TabDelimitedFileUtil.getPartString(oncoUniprotAccessionIndex, parts)); - record.setOncotatorCodonChange(TabDelimitedFileUtil.getPartString(oncoCodonChangeIndex, parts)); - record.setOncotatorProteinPosStart(TabDelimitedFileUtil.getPartInt(oncoProteinPosStartIndex, parts)); - record.setOncotatorProteinPosEnd(TabDelimitedFileUtil.getPartInt(oncoProteinPosEndIndex, parts)); + record.setMafVariantClassification(TabDelimitedFileUtil.getPartString(oncoVariantClassificationIndex, parts)); + record.setMafRefseqMrnaId(TabDelimitedFileUtil.getPartString(oncoRefseqMrnaIdIndex, parts)); + record.setMafUniprotAccession(TabDelimitedFileUtil.getPartString(oncoUniprotAccessionIndex, parts)); + record.setMafCodonChange(TabDelimitedFileUtil.getPartString(oncoCodonChangeIndex, parts)); + record.setMafProteinPosStart(TabDelimitedFileUtil.getPartInt(oncoProteinPosStartIndex, parts)); + record.setMafProteinPosEnd(TabDelimitedFileUtil.getPartInt(oncoProteinPosEndIndex, parts)); // custom filtering of passenger and driver mutations columns record.setDriverFilter(TabDelimitedFileUtil.getPartStringAllowEmptyAndNA(driverIndex, parts)); @@ -640,10 +613,6 @@ public int getOncoVariantClassificationIndex() { return oncoVariantClassificationIndex; } - public int getOncoDbSnpRsIndex() { - return oncoDbSnpRsIndex; - } - public int getMaFImpactIndex() { return maFImpactIndex; } @@ -668,10 +637,6 @@ public int getOncoRefseqMrnaIdIndex() { return oncoRefseqMrnaIdIndex; } - public int getOncoUniprotNameIndex() { - return oncoUniprotNameIndex; - } - public int getOncoCodonChangeIndex() { return oncoCodonChangeIndex; } diff --git a/model/src/main/java/org/cbioportal/model/AlterationCountBase.java b/model/src/main/java/org/cbioportal/model/AlterationCountBase.java new file mode 100644 index 00000000000..cbe79790563 --- /dev/null +++ b/model/src/main/java/org/cbioportal/model/AlterationCountBase.java @@ -0,0 +1,51 @@ +package org.cbioportal.model; + +import java.io.Serializable; +import java.util.Set; + +public abstract class AlterationCountBase implements Serializable { + + private Integer numberOfAlteredCases; + private Integer totalCount; + private Integer numberOfProfiledCases; + private Set matchingGenePanelIds; + + public Integer getNumberOfAlteredCases() { + return numberOfAlteredCases; + } + + public void setNumberOfAlteredCases(Integer numberOfAlteredCases) { + this.numberOfAlteredCases = numberOfAlteredCases; + } + + public Integer getTotalCount() { + return totalCount; + } + + public void setTotalCount(Integer totalCount) { + this.totalCount = totalCount; + } + + public Integer getNumberOfProfiledCases() { + return numberOfProfiledCases; + } + + public void setNumberOfProfiledCases(Integer numberOfProfiledCases) { + this.numberOfProfiledCases = numberOfProfiledCases; + } + + public Set getMatchingGenePanelIds() { + return matchingGenePanelIds; + } + + public void setMatchingGenePanelIds(Set matchingGenePanelIds) { + this.matchingGenePanelIds = matchingGenePanelIds; + } + + public abstract String getUniqueEventKey(); + + public abstract String[] getHugoGeneSymbols(); + + public abstract Integer[] getEntrezGeneIds(); + +} diff --git a/model/src/main/java/org/cbioportal/model/AlterationCountByGene.java b/model/src/main/java/org/cbioportal/model/AlterationCountByGene.java index 702db2c3074..d3a6ecf3d62 100644 --- a/model/src/main/java/org/cbioportal/model/AlterationCountByGene.java +++ b/model/src/main/java/org/cbioportal/model/AlterationCountByGene.java @@ -1,18 +1,13 @@ package org.cbioportal.model; -import java.io.Serializable; import java.math.BigDecimal; -import java.util.Set; -public class AlterationCountByGene implements Serializable { +public class AlterationCountByGene extends AlterationCountBase { private Integer entrezGeneId; private String hugoGeneSymbol; private Integer numberOfAlteredCases; - private Integer totalCount; - private Integer numberOfProfiledCases; private BigDecimal qValue; - private Set matchingGenePanelIds; public Integer getEntrezGeneId() { return entrezGeneId; @@ -38,22 +33,6 @@ public void setNumberOfAlteredCases(Integer numberOfAlteredCases) { this.numberOfAlteredCases = numberOfAlteredCases; } - public Integer getTotalCount() { - return totalCount; - } - - public void setTotalCount(Integer totalCount) { - this.totalCount = totalCount; - } - - public Integer getNumberOfProfiledCases() { - return numberOfProfiledCases; - } - - public void setNumberOfProfiledCases(Integer numberOfProfiledCases) { - this.numberOfProfiledCases = numberOfProfiledCases; - } - public BigDecimal getqValue() { return qValue; } @@ -62,11 +41,19 @@ public void setqValue(BigDecimal qValue) { this.qValue = qValue; } - public Set getMatchingGenePanelIds() { - return matchingGenePanelIds; + @Override + public String getUniqueEventKey() { + return hugoGeneSymbol; } - public void setMatchingGenePanelIds(Set matchingGenePanelIds) { - this.matchingGenePanelIds = matchingGenePanelIds; + @Override + public String[] getHugoGeneSymbols() { + return new String[]{hugoGeneSymbol}; } + + @Override + public Integer[] getEntrezGeneIds() { + return new Integer[]{entrezGeneId}; + } + } diff --git a/model/src/main/java/org/cbioportal/model/AlterationCountByStructuralVariant.java b/model/src/main/java/org/cbioportal/model/AlterationCountByStructuralVariant.java new file mode 100644 index 00000000000..88800d1f84f --- /dev/null +++ b/model/src/main/java/org/cbioportal/model/AlterationCountByStructuralVariant.java @@ -0,0 +1,56 @@ +package org.cbioportal.model; + +public class AlterationCountByStructuralVariant extends AlterationCountBase { + + private Integer gene1EntrezGeneId; + private String gene1HugoGeneSymbol; + private Integer gene2EntrezGeneId; + private String gene2HugoGeneSymbol; + + public Integer getGene1EntrezGeneId() { + return gene1EntrezGeneId; + } + + public void setGene1EntrezGeneId(Integer gene1EntrezGeneId) { + this.gene1EntrezGeneId = gene1EntrezGeneId; + } + + public String getGene1HugoGeneSymbol() { + return gene1HugoGeneSymbol; + } + + public void setGene1HugoGeneSymbol(String gene1HugoGeneSymbol) { + this.gene1HugoGeneSymbol = gene1HugoGeneSymbol; + } + + public Integer getGene2EntrezGeneId() { + return gene2EntrezGeneId; + } + + public void setGene2EntrezGeneId(Integer gene2EntrezGeneId) { + this.gene2EntrezGeneId = gene2EntrezGeneId; + } + + public String getGene2HugoGeneSymbol() { + return gene2HugoGeneSymbol; + } + + public void setGene2HugoGeneSymbol(String gene2HugoGeneSymbol) { + this.gene2HugoGeneSymbol = gene2HugoGeneSymbol; + } + + @Override + public String getUniqueEventKey() { + return gene1HugoGeneSymbol + "::" + gene2HugoGeneSymbol; + } + + @Override + public String[] getHugoGeneSymbols() { + return new String[]{gene1HugoGeneSymbol, gene2HugoGeneSymbol}; + } + + @Override + public Integer[] getEntrezGeneIds() { + return new Integer[]{gene1EntrezGeneId, gene2EntrezGeneId}; + } +} diff --git a/model/src/main/java/org/cbioportal/model/Binnable.java b/model/src/main/java/org/cbioportal/model/Binnable.java new file mode 100644 index 00000000000..358cafc1685 --- /dev/null +++ b/model/src/main/java/org/cbioportal/model/Binnable.java @@ -0,0 +1,13 @@ +package org.cbioportal.model; + +/** + * Data that can be binned, clinical or custom + */ +public interface Binnable { + String getAttrId(); + String getAttrValue(); + String getSampleId(); + String getPatientId(); + String getStudyId(); + Boolean isPatientAttribute(); +} \ No newline at end of file diff --git a/model/src/main/java/org/cbioportal/model/CancerStudyTags.java b/model/src/main/java/org/cbioportal/model/CancerStudyTags.java index d13592afff1..48f987036c0 100644 --- a/model/src/main/java/org/cbioportal/model/CancerStudyTags.java +++ b/model/src/main/java/org/cbioportal/model/CancerStudyTags.java @@ -5,6 +5,7 @@ public class CancerStudyTags implements Serializable { private Integer cancerStudyId; + private String studyId; private String tags; public Integer getCancerStudyId() { @@ -22,4 +23,12 @@ public String getTags() { public void setTags(String tags) { this.tags = tags; } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } } \ No newline at end of file diff --git a/model/src/main/java/org/cbioportal/model/ClinicalData.java b/model/src/main/java/org/cbioportal/model/ClinicalData.java index 63f515fdfb5..b7118588297 100644 --- a/model/src/main/java/org/cbioportal/model/ClinicalData.java +++ b/model/src/main/java/org/cbioportal/model/ClinicalData.java @@ -2,7 +2,7 @@ import javax.validation.constraints.NotNull; -public class ClinicalData extends UniqueKeyBase { +public class ClinicalData extends UniqueKeyBase implements Binnable { private Integer internalId; private String sampleId; @@ -51,6 +51,13 @@ public String getAttrId() { return attrId; } + public Boolean isPatientAttribute() { + if(clinicalAttribute == null) { + return null; + } + return this.clinicalAttribute.getPatientAttribute(); + } + public void setAttrId(String attrId) { this.attrId = attrId; } diff --git a/model/src/main/java/org/cbioportal/model/ClinicalDataCollection.java b/model/src/main/java/org/cbioportal/model/ClinicalDataCollection.java index 7e731104b59..a1ed029ef22 100644 --- a/model/src/main/java/org/cbioportal/model/ClinicalDataCollection.java +++ b/model/src/main/java/org/cbioportal/model/ClinicalDataCollection.java @@ -5,9 +5,16 @@ public class ClinicalDataCollection { + /** + * Paginated resource + */ private List sampleClinicalData = new ArrayList<>(); - private List patientClinicalData = new ArrayList<>(); + /** + * Patient info associated with paginated samples + */ + private List patientClinicalData = new ArrayList<>(); + public List getSampleClinicalData() { return sampleClinicalData; } diff --git a/model/src/main/java/org/cbioportal/model/CopyNumberCountByGene.java b/model/src/main/java/org/cbioportal/model/CopyNumberCountByGene.java index 92c3b596765..ef1143066e7 100644 --- a/model/src/main/java/org/cbioportal/model/CopyNumberCountByGene.java +++ b/model/src/main/java/org/cbioportal/model/CopyNumberCountByGene.java @@ -22,4 +22,9 @@ public String getCytoband() { public void setCytoband(String cytoband) { this.cytoband = cytoband; } + + @Override + public String getUniqueEventKey() { + return getEntrezGeneId().toString() + getAlteration().toString(); + } } diff --git a/model/src/main/java/org/cbioportal/model/GenericAssayBinaryEnrichment.java b/model/src/main/java/org/cbioportal/model/GenericAssayBinaryEnrichment.java new file mode 100644 index 00000000000..f7ccbc7c3b5 --- /dev/null +++ b/model/src/main/java/org/cbioportal/model/GenericAssayBinaryEnrichment.java @@ -0,0 +1,19 @@ +package org.cbioportal.model; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.util.List; + +public class GenericAssayBinaryEnrichment extends GenericAssayEnrichment { + @NotNull + private List counts; + + public List getCounts() { + return counts; + } + + public void setCounts(List counts) { + this.counts = counts; + } + +} diff --git a/model/src/main/java/org/cbioportal/model/GenericAssayCategoricalEnrichment.java b/model/src/main/java/org/cbioportal/model/GenericAssayCategoricalEnrichment.java new file mode 100644 index 00000000000..2fdb661cf38 --- /dev/null +++ b/model/src/main/java/org/cbioportal/model/GenericAssayCategoricalEnrichment.java @@ -0,0 +1,18 @@ +package org.cbioportal.model; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +public class GenericAssayCategoricalEnrichment extends GenericAssayEnrichment { + @NotNull + private BigDecimal qValue; + + public BigDecimal getqValue() { + return qValue; + } + + public void setqValue(BigDecimal qValue) { + this.qValue = qValue; + } + +} diff --git a/model/src/main/java/org/cbioportal/model/GenericAssayCountSummary.java b/model/src/main/java/org/cbioportal/model/GenericAssayCountSummary.java new file mode 100644 index 00000000000..2f24ed760ba --- /dev/null +++ b/model/src/main/java/org/cbioportal/model/GenericAssayCountSummary.java @@ -0,0 +1,38 @@ +package org.cbioportal.model; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +public class GenericAssayCountSummary implements Serializable { + + @NotNull + private String name; + @NotNull + private Integer count; + @NotNull + private Integer totalCount; + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getTotalCount() { + return totalCount; + } + + public void setTotalCount(Integer totalCount) { + this.totalCount = totalCount; + } +} diff --git a/model/src/main/java/org/cbioportal/model/GenericAssayEnrichment.java b/model/src/main/java/org/cbioportal/model/GenericAssayEnrichment.java index 8278694f9be..02491c2221b 100644 --- a/model/src/main/java/org/cbioportal/model/GenericAssayEnrichment.java +++ b/model/src/main/java/org/cbioportal/model/GenericAssayEnrichment.java @@ -1,6 +1,7 @@ package org.cbioportal.model; import java.io.Serializable; +import java.math.BigDecimal; import java.util.HashMap; import javax.validation.constraints.NotNull; @@ -11,6 +12,8 @@ public class GenericAssayEnrichment extends ExpressionEnrichment implements Seri private String stableId; @NotNull private String name; + @NotNull + private BigDecimal qValue; @NotNull private HashMap genericEntityMetaProperties; @@ -37,5 +40,16 @@ public HashMap getGenericEntityMetaProperties() { public void setGenericEntityMetaProperties(HashMap genericEntityMetaProperties) { this.genericEntityMetaProperties = genericEntityMetaProperties; } - + + public BigDecimal getqValue() { + return qValue; + } + + public void setqValue(BigDecimal qValue) { + this.qValue = qValue; + } + + public static int compare(GenericAssayEnrichment c1, GenericAssayEnrichment c2) { + return c1.getpValue().compareTo(c2.getpValue()); + } } diff --git a/model/src/main/java/org/cbioportal/model/GenomicDataCountItem.java b/model/src/main/java/org/cbioportal/model/GenomicDataCountItem.java new file mode 100644 index 00000000000..bd9ae14cdaf --- /dev/null +++ b/model/src/main/java/org/cbioportal/model/GenomicDataCountItem.java @@ -0,0 +1,35 @@ +package org.cbioportal.model; + +import java.io.Serializable; +import java.util.List; + +public class GenomicDataCountItem implements Serializable { + + private String hugoGeneSymbol; + private String profileType; + private List counts; + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public String getProfileType() { + return profileType; + } + + public void setProfileType(String profileType) { + this.profileType = profileType; + } + + public List getCounts() { + return counts; + } + + public void setCounts(List counts) { + this.counts = counts; + } +} diff --git a/model/src/main/java/org/cbioportal/model/Mutation.java b/model/src/main/java/org/cbioportal/model/Mutation.java index 78ee86d4344..62fc787e288 100644 --- a/model/src/main/java/org/cbioportal/model/Mutation.java +++ b/model/src/main/java/org/cbioportal/model/Mutation.java @@ -23,16 +23,11 @@ public class Mutation extends Alteration implements Serializable { private String tumorSeqAllele; private String proteinChange; private String mutationType; - private String functionalImpactScore; - private BigDecimal fisValue; - private String linkXvar; - private String linkPdb; - private String linkMsa; private String ncbiBuild; private String variantType; - private String oncotatorRefseqMrnaId; - private Integer oncotatorProteinPosStart; - private Integer oncotatorProteinPosEnd; + private String refseqMrnaId; + private Integer proteinPosStart; + private Integer proteinPosEnd; private String keyword; private AlleleSpecificCopyNumber alleleSpecificCopyNumber; @JsonRawValue @@ -155,46 +150,6 @@ public void setMutationType(String mutationType) { this.mutationType = mutationType; } - public String getFunctionalImpactScore() { - return functionalImpactScore; - } - - public void setFunctionalImpactScore(String functionalImpactScore) { - this.functionalImpactScore = functionalImpactScore; - } - - public BigDecimal getFisValue() { - return fisValue; - } - - public void setFisValue(BigDecimal fisValue) { - this.fisValue = fisValue; - } - - public String getLinkXvar() { - return linkXvar; - } - - public void setLinkXvar(String linkXvar) { - this.linkXvar = linkXvar; - } - - public String getLinkPdb() { - return linkPdb; - } - - public void setLinkPdb(String linkPdb) { - this.linkPdb = linkPdb; - } - - public String getLinkMsa() { - return linkMsa; - } - - public void setLinkMsa(String linkMsa) { - this.linkMsa = linkMsa; - } - public String getNcbiBuild() { return ncbiBuild; } @@ -210,29 +165,28 @@ public String getVariantType() { public void setVariantType(String variantType) { this.variantType = variantType; } - - public String getOncotatorRefseqMrnaId() { - return oncotatorRefseqMrnaId; + public String getRefseqMrnaId() { + return refseqMrnaId; } - public void setOncotatorRefseqMrnaId(String oncotatorRefseqMrnaId) { - this.oncotatorRefseqMrnaId = oncotatorRefseqMrnaId; + public void setRefseqMrnaId(String refseqMrnaId) { + this.refseqMrnaId = refseqMrnaId; } - - public Integer getOncotatorProteinPosStart() { - return oncotatorProteinPosStart; + + public Integer getProteinPosStart() { + return proteinPosStart; } - public void setOncotatorProteinPosStart(Integer oncotatorProteinPosStart) { - this.oncotatorProteinPosStart = oncotatorProteinPosStart; + public void setProteinPosStart(Integer proteinPosStart) { + this.proteinPosStart = proteinPosStart; } - public Integer getOncotatorProteinPosEnd() { - return oncotatorProteinPosEnd; + public Integer getProteinPosEnd() { + return proteinPosEnd; } - public void setOncotatorProteinPosEnd(Integer oncotatorProteinPosEnd) { - this.oncotatorProteinPosEnd = oncotatorProteinPosEnd; + public void setProteinPosEnd(Integer proteinPosEnd) { + this.proteinPosEnd = proteinPosEnd; } public String getKeyword() { diff --git a/model/src/main/java/org/cbioportal/model/StructuralVariantFilterQuery.java b/model/src/main/java/org/cbioportal/model/StructuralVariantFilterQuery.java new file mode 100644 index 00000000000..0b857f2367a --- /dev/null +++ b/model/src/main/java/org/cbioportal/model/StructuralVariantFilterQuery.java @@ -0,0 +1,48 @@ +package org.cbioportal.model; + +import org.cbioportal.model.util.Select; +import org.springframework.lang.Nullable; + +import java.io.Serializable; + +public class StructuralVariantFilterQuery extends BaseAlterationFilter implements Serializable { + + private StructuralVariantGeneSubQuery gene1Query; + private StructuralVariantGeneSubQuery gene2Query; + + public StructuralVariantFilterQuery() {} + + public StructuralVariantFilterQuery(String gene1HugoSymbol, + @Nullable Integer gene1EntrezId, + String gene2HugoSymbol, + @Nullable Integer gene2EntrezId, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + Select tiersSelect, + boolean includeUnknownTier, + boolean includeGermline, + boolean includeSomatic, + boolean includeUnknownStatus) { + super(includeDriver, includeVUS, includeUnknownOncogenicity, includeGermline, includeSomatic, includeUnknownStatus, tiersSelect, includeUnknownTier); + this.gene1Query = new StructuralVariantGeneSubQuery(gene1HugoSymbol, gene1EntrezId); + this.gene2Query = new StructuralVariantGeneSubQuery(gene2HugoSymbol, gene2EntrezId); + } + + public StructuralVariantGeneSubQuery getGene1Query() { + return gene1Query; + } + + public void setGene1Query(StructuralVariantGeneSubQuery gene1Query) { + this.gene1Query = gene1Query; + } + + public StructuralVariantGeneSubQuery getGene2Query() { + return gene2Query; + } + + public void setGene2Query(StructuralVariantGeneSubQuery gene2Query) { + this.gene2Query = gene2Query; + } + +} diff --git a/model/src/main/java/org/cbioportal/model/StructuralVariantGeneSubQuery.java b/model/src/main/java/org/cbioportal/model/StructuralVariantGeneSubQuery.java index 001652b51a0..e393e0c2d58 100644 --- a/model/src/main/java/org/cbioportal/model/StructuralVariantGeneSubQuery.java +++ b/model/src/main/java/org/cbioportal/model/StructuralVariantGeneSubQuery.java @@ -49,6 +49,10 @@ public StructuralVariantGeneSubQuery(StructuralVariantSpecialValue specialValue) public StructuralVariantGeneSubQuery(String hugoSymbol, Integer entrezId) { this.entrezId = entrezId; + this.hugoSymbol = hugoSymbol; + if (hugoSymbol == null && entrezId == null) { + this.specialValue = StructuralVariantSpecialValue.NO_GENE; + } } @Nullable diff --git a/model/src/main/java/org/cbioportal/model/StudyViewStructuralVariantFilter.java b/model/src/main/java/org/cbioportal/model/StudyViewStructuralVariantFilter.java new file mode 100644 index 00000000000..84584fb7a59 --- /dev/null +++ b/model/src/main/java/org/cbioportal/model/StudyViewStructuralVariantFilter.java @@ -0,0 +1,63 @@ +package org.cbioportal.model; + +import javax.validation.constraints.AssertTrue; +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +public class StudyViewStructuralVariantFilter implements Serializable { + + private Set molecularProfileIds; + private List> structVarQueries; + + @AssertTrue(message = "'specialValue' field of gene1/gene2 StructVarGeneSubQueries cannot be both ANY_GENE or NO_GENE.") + private boolean isGeneQueriesSpecialValueCorrect() { + return structVarQueries.stream() + .flatMap(queryList -> queryList.stream()) + .filter(structVarFilterQuery -> structVarFilterQuery.getGene1Query().getSpecialValue() != null + && structVarFilterQuery.getGene2Query().getSpecialValue() != null + ) + .noneMatch(structVarFilterQuery -> + structVarFilterQuery.getGene1Query().getSpecialValue() == + structVarFilterQuery.getGene2Query().getSpecialValue() + ); + } + + @AssertTrue(message = "'geneId' field of gene1/gene2 StructVarGeneSubQueries cannot be both null.") + private boolean isGeneQueriesGeneIdCorrect() { + return structVarQueries.stream() + .flatMap(queryList -> queryList.stream()) + .noneMatch(structVarFilterQuery -> + structVarFilterQuery.getGene1Query().getHugoSymbol() == null && + structVarFilterQuery.getGene2Query().getHugoSymbol() == null + ); + } + + @AssertTrue(message = "'geneId' field of gene1/gene2 StructVarGeneSubQueries cannot be null when no specialValue set.") + private boolean isGeneQueriesHasGeneIdWhenSpecialValueNull() { + return structVarQueries.stream() + .flatMap(queryList -> queryList.stream()) + .noneMatch(structVarFilterQuery -> + (structVarFilterQuery.getGene1Query().getHugoSymbol() == null && + structVarFilterQuery.getGene1Query().getSpecialValue() == null) + || (structVarFilterQuery.getGene2Query().getHugoSymbol() == null && + structVarFilterQuery.getGene2Query().getSpecialValue() == null) + ); + } + + public Set getMolecularProfileIds() { + return molecularProfileIds; + } + + public void setMolecularProfileIds(Set molecularProfileIds) { + this.molecularProfileIds = molecularProfileIds; + } + + public List> getStructVarQueries() { + return structVarQueries; + } + + public void setStructVarQueries(List> structVarQueries) { + this.structVarQueries = structVarQueries; + } +} \ No newline at end of file diff --git a/persistence/persistence-api/src/main/java/org/cbioportal/persistence/AlterationRepository.java b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/AlterationRepository.java index a94abd42121..b8f436eea09 100644 --- a/persistence/persistence-api/src/main/java/org/cbioportal/persistence/AlterationRepository.java +++ b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/AlterationRepository.java @@ -10,23 +10,31 @@ public interface AlterationRepository { @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSampleAlterationCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter); + List getSampleAlterationGeneCounts(Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter); @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getPatientAlterationCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter); + List getPatientAlterationGeneCounts(Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter); @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSampleCnaCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter); + List getSampleCnaGeneCounts(Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter); @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getPatientCnaCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter); + List getPatientCnaGeneCounts(Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter); + + @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") + List getSampleStructuralVariantCounts(Set molecularProfileCaseIdentifiers, + AlterationFilter alterationFilter); + + @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") + List getPatientStructuralVariantCounts(Set molecularProfileCaseIdentifiers, + AlterationFilter alterationFilter); } diff --git a/persistence/persistence-api/src/main/java/org/cbioportal/persistence/ClinicalDataRepository.java b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/ClinicalDataRepository.java index 0b9f6bf4093..2ff7c09087f 100644 --- a/persistence/persistence-api/src/main/java/org/cbioportal/persistence/ClinicalDataRepository.java +++ b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/ClinicalDataRepository.java @@ -47,9 +47,13 @@ BaseMeta fetchMetaClinicalDataInStudy(String studyId, List ids, List fetchClinicalData(List studyIds, List ids, List attributeIds, String clinicalDataType, String projection); - List fetchSampleClinicalDataClinicalTable(List studyIds, List ids, - Integer pageSize, Integer pageNumber, String searchTerm, - String sortBy, String direction); + List fetchSampleClinicalTable(List studyIds, List ids, + Integer pageSize, Integer pageNumber, String searchTerm, + String sortBy, String direction); + + @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") + Integer fetchSampleClinicalTableCount(List studyIds, List ids, String searchTerm, + String sortBy, String direction); @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") BaseMeta fetchMetaClinicalData(List studyIds, List ids, List attributeIds, diff --git a/persistence/persistence-api/src/main/java/org/cbioportal/persistence/StructuralVariantRepository.java b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/StructuralVariantRepository.java index 44df356125b..8818779e193 100644 --- a/persistence/persistence-api/src/main/java/org/cbioportal/persistence/StructuralVariantRepository.java +++ b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/StructuralVariantRepository.java @@ -3,6 +3,7 @@ import java.util.List; import org.cbioportal.model.GeneFilterQuery; +import org.cbioportal.model.StructuralVariantFilterQuery; import org.cbioportal.model.StructuralVariant; import org.cbioportal.model.StructuralVariantQuery; import org.springframework.cache.annotation.Cacheable; @@ -20,4 +21,9 @@ List fetchStructuralVariants(List molecularProfileIds List fetchStructuralVariantsByGeneQueries(List molecularProfileIds, List sampleIds, List geneQueries); + + @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") + List fetchStructuralVariantsByStructVarQueries(List molecularProfileIds, + List sampleIds, + List structVarQueries); } diff --git a/persistence/persistence-api/src/main/java/org/cbioportal/persistence/TreatmentRepository.java b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/TreatmentRepository.java index 83fb9e1fedb..bc2e0705b16 100644 --- a/persistence/persistence-api/src/main/java/org/cbioportal/persistence/TreatmentRepository.java +++ b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/TreatmentRepository.java @@ -14,20 +14,18 @@ public interface TreatmentRepository { public Map> getTreatmentsByPatientId(List sampleIds, List studyIds, ClinicalEventKeyCode key); @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Map> getSamplesByPatientId(List sampleIds, List studyIds); + public List getTreatments(List sampleIds, List studyIds, ClinicalEventKeyCode key); @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Map> getShallowSamplesByPatientId(List sampleIds, List studyIds); + public Map> getSamplesByPatientId(List sampleIds, List studyIds); @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Set getAllUniqueTreatments(List sampleIds, List studyIds, ClinicalEventKeyCode key); + public Map> getShallowSamplesByPatientId(List sampleIds, List studyIds); @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Integer getTreatmentCount(List studies, String key); + public Boolean hasTreatmentData(List studies, ClinicalEventKeyCode key); @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Integer getSampleCount(List studies); + public Boolean hasSampleTimelineData(List studies); - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Boolean studyIdHasTreatments(String studyId, ClinicalEventKeyCode key); } diff --git a/persistence/persistence-api/src/main/java/org/cbioportal/persistence/config/RedisConfig.java b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/config/RedisConfig.java index 9aad4491870..2da81e8787c 100644 --- a/persistence/persistence-api/src/main/java/org/cbioportal/persistence/config/RedisConfig.java +++ b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/config/RedisConfig.java @@ -2,14 +2,17 @@ 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.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.interceptor.CacheErrorHandler; import org.springframework.cache.interceptor.CacheResolver; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.cache.interceptor.NamedCacheResolver; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -29,6 +32,11 @@ public CacheManager cacheManager() { ); } + @Override + public CacheErrorHandler errorHandler() { + return new LoggingCacheErrorHandler(); + } + @Bean @Override public KeyGenerator keyGenerator() { diff --git a/persistence/persistence-api/src/main/java/org/cbioportal/persistence/util/LoggingCacheErrorHandler.java b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/util/LoggingCacheErrorHandler.java new file mode 100644 index 00000000000..a682c568dca --- /dev/null +++ b/persistence/persistence-api/src/main/java/org/cbioportal/persistence/util/LoggingCacheErrorHandler.java @@ -0,0 +1,43 @@ +package org.cbioportal.persistence.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cache.Cache; +import org.springframework.cache.interceptor.CacheErrorHandler; + +/** + * Implementation of org.springframework.cache.interceptor.CacheErrorHandler + * that logs the error messages when performing Redis operations. + * Redis will throw a RuntimeException causing our APIs to return HTTP 500 responses, so we defined + * this class to just log the errors and allow our app fallback to the non-cached version. + */ + +public class LoggingCacheErrorHandler implements CacheErrorHandler { + + private static final Logger LOG = LoggerFactory.getLogger(LoggingCacheErrorHandler.class); + + @Override + public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) { + LOG.error(String.format("Cache '%s' failed to get entry with key '%s'", cache.getName(), key), exception); + LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); + } + + @Override + public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) { + LOG.error(String.format("Cache '%s' failed to put entry with key '%s'", cache.getName(), key), exception); + LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); + } + + @Override + public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) { + LOG.error(String.format("Cache '%s' failed to evict entry with key '%s'", cache.getName(), key), exception); + LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); + } + + @Override + public void handleCacheClearError(RuntimeException exception, Cache cache) { + LOG.error(String.format("Cache '%s' failed to clear entries", cache.getName()), exception); + LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); + } + +} diff --git a/persistence/persistence-connections/src/main/resources/applicationContext-persistenceConnections.xml b/persistence/persistence-connections/src/main/resources/applicationContext-persistenceConnections.xml index ad782e64fba..1259e8621cf 100644 --- a/persistence/persistence-connections/src/main/resources/applicationContext-persistenceConnections.xml +++ b/persistence/persistence-connections/src/main/resources/applicationContext-persistenceConnections.xml @@ -44,7 +44,15 @@ - + + + + + mysql + h2 + + + @@ -60,6 +68,7 @@ + diff --git a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/AlterationCountsMapper.java b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/AlterationCountsMapper.java index 9ee625a0383..4b1461cdbb8 100644 --- a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/AlterationCountsMapper.java +++ b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/AlterationCountsMapper.java @@ -1,6 +1,7 @@ package org.cbioportal.persistence.mybatis; import org.cbioportal.model.AlterationCountByGene; +import org.cbioportal.model.AlterationCountByStructuralVariant; import org.cbioportal.model.CopyNumberCountByGene; import org.cbioportal.model.MolecularProfileCaseIdentifier; import org.cbioportal.model.util.Select; @@ -10,7 +11,7 @@ public interface AlterationCountsMapper { /** - * Calculate sample-level counts of mutation and discrete CNA alteration events. + * Calculate sample-level counts of mutation and discrete CNA alteration events in genes. * @param entrezGeneIds Gene ids to get counts for. * @param mutationTypes Types of mutations to include in alteration counts. * @param cnaTypes Types of discrete copy number alteration types to include in alteration counts. @@ -23,7 +24,7 @@ public interface AlterationCountsMapper { * @param includeSomatic Include somatic mutations in alteration counts * @return Gene-level counts of (1) the total number of alterations and (2) the number of altered samples. */ - List getSampleAlterationCounts(List mutationMolecularProfileCaseIdentifiers, + List getSampleAlterationGeneCounts(List mutationMolecularProfileCaseIdentifiers, List cnaMolecularProfileCaseIdentifiers, List structuralVariantMolecularProfileCaseIdentifiers, Select entrezGeneIds, @@ -38,7 +39,7 @@ List getSampleAlterationCounts(List getSampleAlterationCounts(List getPatientAlterationCounts(List mutationMolecularProfileCaseIdentifiers, + List getPatientAlterationGeneCounts(List mutationMolecularProfileCaseIdentifiers, List cnaMolecularProfileCaseIdentifiers, List structuralVariantMolecularProfileCaseIdentifiers, Select entrezGeneIds, @@ -68,7 +69,7 @@ List getPatientAlterationCounts(List getSampleCnaCounts(List cnaMolecularProfileCaseIdentifiers, + List getSampleCnaGeneCounts(List cnaMolecularProfileCaseIdentifiers, Select entrezGeneIds, Select cnaTypes, boolean includeDriver, @@ -78,7 +79,7 @@ List getSampleCnaCounts(List getPatientCnaCounts(List cnaMolecularProfileCaseIdentifiers, + List getPatientCnaGeneCounts(List cnaMolecularProfileCaseIdentifiers, Select entrezGeneIds, Select cnaTypes, boolean includeDriver, @@ -88,4 +89,46 @@ List getPatientCnaCounts(List getMolecularProfileCaseInternalIdentifier(List molecularProfileSampleIdentifiers, String caseType); + + /** + * Calculate sample-level counts of structural variant events. + * @param includeDriver Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. + * @param includeVUS Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. + * @param includeUnknownOncogenicity Include variants that are not annotated as driver or VUS. Uses annotations loaded as 'custom driver annotations'. + * @param selectedTiers Force alterations assigned to a tier to be interpreted as driver events. Uses tier annotations loaded as 'custom driver annotation tiers'. + * @param includeUnknownTier Include mutations that have unspecified tier, or tiers with '', 'NA' or 'unknown' in alteration counts + * @param includeGermline Include germline mutations in alteration counts + * @param includeSomatic Include somatic mutations in alteration counts + * @return StructVar-level counts (GeneA::GeneB) of (1) the total number of alterations and (2) the number of altered samples. + */ + List getSampleStructuralVariantCounts(List structuralVariantMolecularProfileCaseIdentifiers, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + Select selectedTiers, + boolean includeUnknownTier, + boolean includeGermline, + boolean includeSomatic, + boolean includeUnknownStatus); + /** + * Calculate patient-level counts of structural variant events. + * @param includeDriver Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. + * @param includeVUS Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. + * @param includeUnknownOncogenicity Include variants that are not annotated as driver or VUS. Uses annotations loaded as 'custom driver annotations'. + * @param selectedTiers Force alterations assigned to a tier to be interpreted as driver events. Uses tier annotations loaded as 'custom driver annotation tiers'. + * @param includeUnknownTier Include mutations that have unspecified tier, or tiers with '', 'NA' or 'unknown' in alteration counts + * @param includeGermline Include germline mutations in alteration counts + * @param includeSomatic Include somatic mutations in alteration counts + * @return StructVar-level counts (GeneA::GeneB) of (1) the total number of alterations and (2) the number of altered patients. + */ + List getPatientStructuralVariantCounts(List structuralVariantMolecularProfileCaseIdentifiers, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + Select selectedTiers, + boolean includeUnknownTier, + boolean includeGermline, + boolean includeSomatic, + boolean includeUnknownStatus); + } diff --git a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/AlterationMyBatisRepository.java b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/AlterationMyBatisRepository.java index 58b4a5fdb90..a48b6476b59 100644 --- a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/AlterationMyBatisRepository.java +++ b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/AlterationMyBatisRepository.java @@ -1,6 +1,7 @@ package org.cbioportal.persistence.mybatis; import org.cbioportal.model.AlterationCountByGene; +import org.cbioportal.model.AlterationCountByStructuralVariant; import org.cbioportal.model.AlterationFilter; import org.cbioportal.model.CNA; import org.cbioportal.model.CopyNumberCountByGene; @@ -26,17 +27,19 @@ public class AlterationMyBatisRepository implements AlterationRepository { private MolecularProfileRepository molecularProfileRepository; @Override - public List getSampleAlterationCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter) { + public List getSampleAlterationGeneCounts(Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter) { if ((alterationFilter.getMutationTypeSelect().hasNone() && alterationFilter.getCNAEventTypeSelect().hasNone() && !alterationFilter.getStructuralVariants()) || (molecularProfileCaseIdentifiers == null || molecularProfileCaseIdentifiers.isEmpty()) || allAlterationsExcludedDriverAnnotation(alterationFilter) || allAlterationsExcludedMutationStatus(alterationFilter) - || allAlterationsExcludedDriverTierAnnotation(alterationFilter)) { - return Collections.emptyList(); + || allAlterationsExcludedDriverTierAnnotation(alterationFilter) + ) { + // We want a mutable empty list: + return new ArrayList<>(); } Set molecularProfileIds = molecularProfileCaseIdentifiers.stream() @@ -50,7 +53,7 @@ public List getSampleAlterationCounts(Set(molecularProfileCaseIdentifiers), "SAMPLE_ID") .stream() .collect(Collectors.groupingBy(e -> profileTypeByProfileId.getOrDefault(e.getMolecularProfileId(), null))); - return alterationCountsMapper.getSampleAlterationCounts( + return alterationCountsMapper.getSampleAlterationGeneCounts( groupedIdentifiersByProfileType.get(MolecularAlterationType.MUTATION_EXTENDED), groupedIdentifiersByProfileType.get(MolecularAlterationType.COPY_NUMBER_ALTERATION), groupedIdentifiersByProfileType.get(MolecularAlterationType.STRUCTURAL_VARIANT), @@ -68,9 +71,9 @@ public List getSampleAlterationCounts(Set getPatientAlterationCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter) { + public List getPatientAlterationGeneCounts(Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter) { if ((alterationFilter.getMutationTypeSelect().hasNone() && alterationFilter.getCNAEventTypeSelect().hasNone() && !alterationFilter.getStructuralVariants()) @@ -91,12 +94,12 @@ public List getPatientAlterationCounts(List datum.getMolecularProfileId().toString(), MolecularProfile::getMolecularAlterationType)); Map> groupedIdentifiersByProfileType = - alterationCountsMapper.getMolecularProfileCaseInternalIdentifier(molecularProfileCaseIdentifiers, "PATIENT_ID") + alterationCountsMapper.getMolecularProfileCaseInternalIdentifier(new ArrayList<>(molecularProfileCaseIdentifiers), "PATIENT_ID") .stream() .collect(Collectors.groupingBy(e -> profileTypeByProfileId.getOrDefault(e.getMolecularProfileId(), null))); - return alterationCountsMapper.getPatientAlterationCounts( + return alterationCountsMapper.getPatientAlterationGeneCounts( groupedIdentifiersByProfileType.get(MolecularAlterationType.MUTATION_EXTENDED), groupedIdentifiersByProfileType.get(MolecularAlterationType.COPY_NUMBER_ALTERATION), groupedIdentifiersByProfileType.get(MolecularAlterationType.STRUCTURAL_VARIANT), @@ -110,13 +113,14 @@ public List getPatientAlterationCounts(List getSampleCnaCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter) { + public List getSampleCnaGeneCounts(Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter) { if (alterationFilter.getCNAEventTypeSelect().hasNone() || molecularProfileCaseIdentifiers == null || allAlterationsExcludedDriverAnnotation(alterationFilter) @@ -127,7 +131,7 @@ public List getSampleCnaCounts(Set molecularProfileCaseInternalIdentifiers = alterationCountsMapper.getMolecularProfileCaseInternalIdentifier(new ArrayList<>(molecularProfileCaseIdentifiers), "SAMPLE_ID"); - return alterationCountsMapper.getSampleCnaCounts( + return alterationCountsMapper.getSampleCnaGeneCounts( molecularProfileCaseInternalIdentifiers, entrezGeneIds, createCnaTypeList(alterationFilter), @@ -139,9 +143,9 @@ public List getSampleCnaCounts(Set getPatientCnaCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter) { + public List getPatientCnaGeneCounts(Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter) { if (alterationFilter.getCNAEventTypeSelect().hasNone() || molecularProfileCaseIdentifiers == null || allAlterationsExcludedDriverAnnotation(alterationFilter) @@ -149,9 +153,9 @@ public List getPatientCnaCounts(List molecularProfileCaseInternalIdentifiers = - alterationCountsMapper.getMolecularProfileCaseInternalIdentifier(molecularProfileCaseIdentifiers, "PATIENT_ID"); + alterationCountsMapper.getMolecularProfileCaseInternalIdentifier(new ArrayList<>(molecularProfileCaseIdentifiers), "PATIENT_ID"); - return alterationCountsMapper.getPatientCnaCounts( + return alterationCountsMapper.getPatientCnaGeneCounts( molecularProfileCaseInternalIdentifiers, entrezGeneIds, createCnaTypeList(alterationFilter), @@ -162,6 +166,50 @@ public List getPatientCnaCounts(List getSampleStructuralVariantCounts(Set molecularProfileCaseIdentifiers, + AlterationFilter alterationFilter) { + + if (molecularProfileCaseIdentifiers == null + || molecularProfileCaseIdentifiers.isEmpty() + || allAlterationsExcludedMutationStatus(alterationFilter)) { + return Collections.emptyList(); + } + + return alterationCountsMapper.getSampleStructuralVariantCounts( + new ArrayList<>(molecularProfileCaseIdentifiers), + alterationFilter.getIncludeDriver(), + alterationFilter.getIncludeVUS(), + alterationFilter.getIncludeUnknownOncogenicity(), + alterationFilter.getSelectedTiers(), + alterationFilter.getIncludeUnknownTier(), + alterationFilter.getIncludeGermline(), + alterationFilter.getIncludeSomatic(), + alterationFilter.getIncludeUnknownStatus()); + } + + @Override + public List getPatientStructuralVariantCounts(Set molecularProfileCaseIdentifiers, + AlterationFilter alterationFilter) { + + if (molecularProfileCaseIdentifiers == null + || molecularProfileCaseIdentifiers.isEmpty() + || allAlterationsExcludedMutationStatus(alterationFilter)) { + return Collections.emptyList(); + } + + return alterationCountsMapper.getPatientStructuralVariantCounts( + new ArrayList<>(molecularProfileCaseIdentifiers), + alterationFilter.getIncludeDriver(), + alterationFilter.getIncludeVUS(), + alterationFilter.getIncludeUnknownOncogenicity(), + alterationFilter.getSelectedTiers(), + alterationFilter.getIncludeUnknownTier(), + alterationFilter.getIncludeGermline(), + alterationFilter.getIncludeSomatic(), + alterationFilter.getIncludeUnknownStatus()); + } + private Select createCnaTypeList(final AlterationFilter alterationFilter) { if (alterationFilter.getCNAEventTypeSelect().hasNone()) return Select.none(); diff --git a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMapper.java b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMapper.java index 77f92028796..1f4209deffb 100644 --- a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMapper.java +++ b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMapper.java @@ -18,9 +18,12 @@ List getPatientClinicalData(List studyIds, List pa String projection, Integer limit, Integer offset, String sortby, String direction); - List getSampleClinicalDataClinicalTable(List studyIds, List sampleIds, String projection, - Integer limit, Integer offset, String searchTerm, - String sortBy, String direction); + List getSampleClinicalTable(List studyIds, List sampleIds, String projection, + Integer limit, Integer offset, String searchTerm, + String sortBy, String direction); + + Integer getSampleClinicalTableCount(List studyIds, List sampleIds, String projection, + String searchTerm, String sortBy, String direction); BaseMeta getMetaPatientClinicalData(List studyIds, List patientIds, List attributeIds); @@ -33,5 +36,4 @@ List fetchPatientClinicalDataCounts(List studyIds, Li List getPatientClinicalDataDetailedToSample(List studyIds, List patientIds, List attributeIds, String projection, Integer limit, Integer offset, String sortBy, String direction); - } diff --git a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMyBatisRepository.java b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMyBatisRepository.java index 6725e94957e..15c692f84bc 100644 --- a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMyBatisRepository.java +++ b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMyBatisRepository.java @@ -138,17 +138,24 @@ public List fetchClinicalData(List studyIds, List } @Override - public List fetchSampleClinicalDataClinicalTable(List studyIds, List ids, - Integer pageSize, Integer pageNumber, String searchTerm, - String sortBy, String direction) { + public List fetchSampleClinicalTable(List studyIds, List ids, + Integer pageSize, Integer pageNumber, String searchTerm, + String sortBy, String direction) { if (ids.isEmpty()) { return new ArrayList<>(); } int offset = offsetCalculator.calculate(pageSize, pageNumber); - return clinicalDataMapper.getSampleClinicalDataClinicalTable(studyIds, ids,"SUMMARY", pageSize, + return clinicalDataMapper.getSampleClinicalTable(studyIds, ids,"SUMMARY", pageSize, offset, searchTerm, sortBy, direction); } + @Override + public Integer fetchSampleClinicalTableCount(List studyIds, List sampleIds, + String searchTerm, String sortBy, String direction) { + return clinicalDataMapper.getSampleClinicalTableCount(studyIds, sampleIds,"SUMMARY", + searchTerm, sortBy, direction); + } + @Override public BaseMeta fetchMetaClinicalData(List studyIds, List ids, List attributeIds, String clinicalDataType) { diff --git a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMapper.java b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMapper.java index c4705d8de06..2a24f753b0d 100644 --- a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMapper.java +++ b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMapper.java @@ -26,6 +26,7 @@ import java.util.List; import org.cbioportal.model.GeneFilterQuery; +import org.cbioportal.model.StructuralVariantFilterQuery; import org.cbioportal.model.StructuralVariant; import org.cbioportal.model.StructuralVariantQuery; @@ -39,4 +40,8 @@ List fetchStructuralVariants(List molecularProfileIds List fetchStructuralVariantsByGeneQueries(List molecularProfileIds, List sampleIds, List geneQueries); + + List fetchStructuralVariantsByStructVarQueries(List molecularProfileIds, + List sampleIds, + List structVarQueries); } diff --git a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMyBatisRepository.java b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMyBatisRepository.java index 18e6e2c5396..f03d42130da 100644 --- a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMyBatisRepository.java +++ b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMyBatisRepository.java @@ -24,6 +24,7 @@ package org.cbioportal.persistence.mybatis; import org.cbioportal.model.GeneFilterQuery; +import org.cbioportal.model.StructuralVariantFilterQuery; import org.cbioportal.model.StructuralVariant; import org.cbioportal.model.StructuralVariantQuery; import org.cbioportal.persistence.StructuralVariantRepository; @@ -73,6 +74,21 @@ public List fetchStructuralVariants(List molecularPro public List fetchStructuralVariantsByGeneQueries(List molecularProfileIds, List sampleIds, List geneQueries) { + if (geneQueries == null || geneQueries.isEmpty() + || molecularProfileIds == null || molecularProfileIds.isEmpty()) { + return new ArrayList<>(); + } return structuralVariantMapper.fetchStructuralVariantsByGeneQueries(molecularProfileIds, sampleIds, geneQueries); } + + @Override + public List fetchStructuralVariantsByStructVarQueries(List molecularProfileIds, + List sampleIds, + List structVarQueries) { + if (structVarQueries == null || structVarQueries.isEmpty() + || molecularProfileIds == null || molecularProfileIds.isEmpty()) { + return new ArrayList<>(); + } + return structuralVariantMapper.fetchStructuralVariantsByStructVarQueries(molecularProfileIds, sampleIds, structVarQueries); + } } diff --git a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMapper.java b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMapper.java index 6d748341dbd..44e4f856079 100644 --- a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMapper.java +++ b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMapper.java @@ -13,11 +13,7 @@ public interface TreatmentMapper { List getAllShallowSamples(List sampleIds, List studyIds); - Set getAllUniqueTreatments(List sampleIds, List studyIds, String key); + Boolean hasTreatmentData(List sampleIds, List studyIds, String key); - Integer getTreatmentCount(List sampleIds, List studyIds, String key); - - Integer getSampleCount(List sampleIds, List studyIds); - - Boolean studyIdHasTreatments(String studyId, String key); + Boolean hasSampleTimelineData(List sampleIds, List studyIds); } diff --git a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMyBatisRepository.java b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMyBatisRepository.java index efa6efb27a9..d44bdfc808a 100644 --- a/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMyBatisRepository.java +++ b/persistence/persistence-mybatis/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMyBatisRepository.java @@ -18,12 +18,17 @@ public class TreatmentMyBatisRepository implements TreatmentRepository { @Override public Map> getTreatmentsByPatientId(List sampleIds, List studyIds, ClinicalEventKeyCode key) { + return getTreatments(sampleIds, studyIds, key) + .stream() + .collect(groupingBy(Treatment::getPatientId)); + } + + @Override + public List getTreatments(List sampleIds, List studyIds, ClinicalEventKeyCode key) { return treatmentMapper.getAllTreatments(sampleIds, studyIds, key.getKey()) .stream() .flatMap(treatment -> splitIfDelimited(treatment, key)) - .collect(groupingBy(Treatment::getPatientId)); - - + .collect(Collectors.toList()); } private Stream splitIfDelimited(Treatment unsplitTreatment, ClinicalEventKeyCode key) { @@ -61,31 +66,12 @@ public Map> getShallowSamplesByPatientId(List< } @Override - public Set getAllUniqueTreatments(List sampleIds, List studyIds, ClinicalEventKeyCode key) { - return treatmentMapper.getAllUniqueTreatments(sampleIds, studyIds, key.getKey()) - .stream() - .flatMap(treatment -> { - if (key.isDelimited()) { - return Arrays.stream(treatment.split(key.getDelimiter())); - } else { - return Stream.of(treatment); - } - }) - .collect(Collectors.toSet()); - } - - @Override - public Integer getTreatmentCount(List studies, String key) { - return treatmentMapper.getTreatmentCount(null, studies, key); - } - - @Override - public Integer getSampleCount(List studies) { - return treatmentMapper.getSampleCount(null, studies); + public Boolean hasTreatmentData(List studies, ClinicalEventKeyCode key) { + return treatmentMapper.hasTreatmentData(null, studies, key.getKey()); } @Override - public Boolean studyIdHasTreatments(String studyId, ClinicalEventKeyCode key) { - return treatmentMapper.studyIdHasTreatments(studyId, key.getKey()); + public Boolean hasSampleTimelineData(List studies) { + return treatmentMapper.hasSampleTimelineData(null, studies); } } diff --git a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/AlterationCountsMapper.xml b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/AlterationCountsMapper.xml index cd8ec8761b2..01ed5f7bae7 100644 --- a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/AlterationCountsMapper.xml +++ b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/AlterationCountsMapper.xml @@ -3,7 +3,7 @@ - SELECT ENTREZ_GENE_ID AS entrezGeneId, HUGO_GENE_SYMBOL AS hugoGeneSymbol, @@ -37,7 +37,7 @@ GROUP BY ENTREZ_GENE_ID, HUGO_GENE_SYMBOL; - SELECT ENTREZ_GENE_ID AS entrezGeneId, HUGO_GENE_SYMBOL AS hugoGeneSymbol, @@ -71,7 +71,7 @@ GROUP BY ENTREZ_GENE_ID, HUGO_GENE_SYMBOL; - SELECT cna_event.ENTREZ_GENE_ID AS entrezGeneId, gene.HUGO_GENE_SYMBOL AS hugoGeneSymbol, @@ -111,7 +111,7 @@ GROUP BY cna_event.ENTREZ_GENE_ID, cna_event.ALTERATION, reference_genome_gene.CYTOBAND, gene.HUGO_GENE_SYMBOL - SELECT cna_event.ENTREZ_GENE_ID AS entrezGeneId, gene.HUGO_GENE_SYMBOL AS hugoGeneSymbol, @@ -147,6 +147,60 @@ GROUP BY cna_event.ENTREZ_GENE_ID, cna_event.ALTERATION, gene.HUGO_GENE_SYMBOL + + + + @@ -176,6 +230,29 @@ + + + + + + + + LEFT JOIN alteration_driver_annotation ON + structural_variant.INTERNAL_ID = alteration_driver_annotation.ALTERATION_EVENT_ID + AND structural_variant.GENETIC_PROFILE_ID = alteration_driver_annotation.GENETIC_PROFILE_ID + AND structural_variant.SAMPLE_ID = alteration_driver_annotation.SAMPLE_ID + + + + + + ( + structural_variant.SITE2_ENTREZ_GENE_ID != structural_variant.SITE1_ENTREZ_GENE_ID + OR + structural_variant.SITE1_ENTREZ_GENE_ID IS NULL + ) + + @@ -183,14 +260,14 @@ - OR LOWER(alteration_driver_annotation.DRIVER_FILTER) = 'putative_driver' + OR LOWER(DRIVER_FILTER) = 'putative_driver' - OR LOWER(alteration_driver_annotation.DRIVER_FILTER) = 'putative_passenger' + OR LOWER(DRIVER_FILTER) = 'putative_passenger' - OR alteration_driver_annotation.DRIVER_FILTER IS NULL - OR LOWER(alteration_driver_annotation.DRIVER_FILTER) IN ('unknown', 'na', '') + OR DRIVER_FILTER IS NULL + OR LOWER(DRIVER_FILTER) IN ('unknown', 'na', '') @@ -211,14 +288,14 @@ - OR alteration_driver_annotation.DRIVER_TIERS_FILTER IN + OR DRIVER_TIERS_FILTER IN #{item} - OR alteration_driver_annotation.DRIVER_TIERS_FILTER IS NULL - OR LOWER(alteration_driver_annotation.DRIVER_TIERS_FILTER) IN ('', 'na', 'unknown') + OR DRIVER_TIERS_FILTER IS NULL + OR LOWER(DRIVER_TIERS_FILTER) IN ('', 'na', 'unknown') @@ -239,7 +316,7 @@ OR - LOWER(mutation.MUTATION_STATUS) = 'germline' + LOWER(mutation.MUTATION_STATUS) LIKE '%germline%' OR @@ -247,7 +324,7 @@ OR - LOWER(mutation.MUTATION_STATUS) NOT IN ('germline', 'somatic') + (LOWER(mutation.MUTATION_STATUS) != 'somatic' AND LOWER(mutation.MUTATION_STATUS) NOT LIKE '%germline%') @@ -268,15 +345,15 @@ OR - LOWER(combinedResults.SV_STATUS) = 'germline' + LOWER(SV_STATUS) = 'germline' OR - LOWER(combinedResults.SV_STATUS) = 'somatic' + LOWER(SV_STATUS) = 'somatic' OR - LOWER(combinedResults.SV_STATUS) NOT IN ('germline', 'somatic') + LOWER(SV_STATUS) NOT IN ('germline', 'somatic') @@ -404,39 +481,47 @@ as caseUniqueId, as caseStableId, genetic_profile.GENETIC_PROFILE_ID as geneticProfileId, - structural_variant.SV_STATUS - + structural_variant.SV_STATUS as SV_STATUS FROM structural_variant INNER JOIN genetic_profile ON structural_variant.GENETIC_PROFILE_ID = genetic_profile.GENETIC_PROFILE_ID INNER JOIN sample ON structural_variant.SAMPLE_ID = sample.INTERNAL_ID INNER JOIN patient ON sample.PATIENT_ID = patient.INTERNAL_ID INNER JOIN gene ON structural_variant.SITE1_ENTREZ_GENE_ID = gene.ENTREZ_GENE_ID + + + + + UNION ALL + SELECT gene.ENTREZ_GENE_ID AS entrezGeneId, gene.HUGO_GENE_SYMBOL AS hugoGeneSymbol, as caseUniqueId, as caseStableId, genetic_profile.GENETIC_PROFILE_ID as geneticProfileId, - structural_variant.SV_STATUS + structural_variant.SV_STATUS as SV_STATUS FROM structural_variant INNER JOIN genetic_profile ON structural_variant.GENETIC_PROFILE_ID = genetic_profile.GENETIC_PROFILE_ID INNER JOIN sample ON structural_variant.SAMPLE_ID = sample.INTERNAL_ID INNER JOIN patient ON sample.PATIENT_ID = patient.INTERNAL_ID INNER JOIN gene ON structural_variant.SITE2_ENTREZ_GENE_ID = gene.ENTREZ_GENE_ID - WHERE structural_variant.SITE2_ENTREZ_GENE_ID != structural_variant.SITE1_ENTREZ_GENE_ID - OR structural_variant.SITE1_ENTREZ_GENE_ID IS NULL + + + + + ) AS combinedResults - - - - - - - - + + + + + + + + diff --git a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalDataMapper.xml b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalDataMapper.xml index d9af9df72e2..29e6cd536c5 100644 --- a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalDataMapper.xml +++ b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalDataMapper.xml @@ -47,6 +47,11 @@ INNER JOIN cancer_study ON patient.CANCER_STUDY_ID = cancer_study.CANCER_STUDY_ID + + + LEFT JOIN clinical_patient ON clinical_patient.INTERNAL_ID = patient.INTERNAL_ID + + FROM clinical_patient INNER JOIN patient ON clinical_patient.INTERNAL_ID = patient.INTERNAL_ID @@ -221,7 +226,7 @@ GROUP BY clinical_patient.ATTR_ID, clinical_patient.ATTR_VALUE - SELECT @@ -230,28 +235,55 @@ + + - INNER JOIN - (SELECT DISTINCT clinical_sample.INTERNAL_ID + INNER JOIN ( + SELECT DISTINCT clinical_sample.INTERNAL_ID - , clinical_sample.ATTR_ID, clinical_sample.ATTR_VALUE + + , sample.STABLE_ID AS SORT_BY + + + , patient.STABLE_ID AS SORT_BY + + + + + , CASE + WHEN clinical_sample.ATTR_ID = #{sortBy} THEN clinical_sample.ATTR_VALUE + WHEN clinical_patient.ATTR_ID = #{sortBy} THEN clinical_patient.ATTR_VALUE + ELSE NULL + END AS SORT_BY + - + AND - clinical_sample.ATTR_VALUE LIKE CONCAT('%','${searchTerm}', '%') + clinical_sample.ATTR_VALUE LIKE CONCAT('%', #{searchTerm}, '%') - AND - clinical_sample.ATTR_ID = '${sortBy}' - ORDER BY clinical_sample.ATTR_VALUE ${direction} + + + + ORDER BY ISNULL(SORT_BY), SORT_BY ${direction} + + + ORDER BY SORT_BY ${direction} NULLS LAST + + + LIMIT #{limit} OFFSET #{offset} - ) as sample_id_subquery - ON clinical_sample.INTERNAL_ID = sample_id_subquery.INTERNAL_ID + ) AS sample_id_subquery + ON clinical_sample.INTERNAL_ID = sample_id_subquery.INTERNAL_ID diff --git a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalEventMapper.xml b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalEventMapper.xml index 3bb73ea761b..44f8083bf2e 100644 --- a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalEventMapper.xml +++ b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalEventMapper.xml @@ -142,7 +142,14 @@ diff --git a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/StructuralVariantMapper.xml b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/StructuralVariantMapper.xml index 7e8037654b6..0fe8bbe8955 100644 --- a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/StructuralVariantMapper.xml +++ b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/StructuralVariantMapper.xml @@ -82,13 +82,67 @@ AND - - (( structural_variant.SITE1_ENTREZ_GENE_ID = '${geneFilterQuery.getEntrezGeneId()}' - OR structural_variant.SITE2_ENTREZ_GENE_ID = '${geneFilterQuery.getEntrezGeneId()}') - - - - + + ( + + + (structural_variant.SITE1_ENTREZ_GENE_ID = ${geneFilterQuery.getEntrezGeneId()} + OR structural_variant.SITE2_ENTREZ_GENE_ID = ${geneFilterQuery.getEntrezGeneId()}) + + + + + + AND structural_variant.SITE1_ENTREZ_GENE_ID IS NULL + + + + AND structural_variant.SITE1_ENTREZ_GENE_ID = ${geneFilterQuery.getGene1Query().getEntrezId()} + + + + + AND + structural_variant.SITE2_ENTREZ_GENE_ID IS NULL + + + + AND + structural_variant.SITE2_ENTREZ_GENE_ID = ${geneFilterQuery.getGene2Query().getEntrezId()} + + + + + + + + + + + + OR LOWER(structural_variant.SV_STATUS) = 'germline' + + + OR LOWER(structural_variant.SV_STATUS) = 'somatic' + + + OR LOWER(structural_variant.SV_STATUS) NOT IN ('somatic', 'germline') + + + ) + + + AND NULL + + + + + + + + + + OR LOWER(alteration_driver_annotation.DRIVER_FILTER) = 'putative_driver' @@ -101,44 +155,45 @@ OR LOWER(alteration_driver_annotation.DRIVER_FILTER) IN ('unknown', 'na', '') - - - AND NULL - - - - - - - - - - - AND NOT alteration_driver_annotation.DRIVER_TIERS_FILTER IS NULL - AND NOT LOWER(alteration_driver_annotation.DRIVER_TIERS_FILTER) IN ('', 'na', 'unknown') - - - - - OR alteration_driver_annotation.DRIVER_TIERS_FILTER IN - - #{item} - - - - OR alteration_driver_annotation.DRIVER_TIERS_FILTER IS NULL - OR LOWER(alteration_driver_annotation.DRIVER_TIERS_FILTER) IN ('', 'na', 'unknown') - - - - - AND NULL - - - - - - ) + + + + AND NULL + + + + + + + + + + + AND NOT alteration_driver_annotation.DRIVER_TIERS_FILTER IS NULL + AND NOT LOWER(alteration_driver_annotation.DRIVER_TIERS_FILTER) IN ('', 'na', 'unknown') + + + + + OR alteration_driver_annotation.DRIVER_TIERS_FILTER IN + + #{item} + + + + OR alteration_driver_annotation.DRIVER_TIERS_FILTER IS NULL + OR LOWER(alteration_driver_annotation.DRIVER_TIERS_FILTER) IN ('', 'na', 'unknown') + + + + + AND NULL + + + + + + ) @@ -160,7 +215,7 @@ - ( + OR ( structural_variant.SITE1_ENTREZ_GENE_ID=#{item.gene1.entrezId} @@ -232,7 +287,36 @@ and structural_variant.INTERNAL_ID = alteration_driver_annotation.ALTERATION_EVENT_ID - + + + + + + ORDER BY gene1.HUGO_GENE_SYMBOL, gene2.HUGO_GENE_SYMBOL + + + diff --git a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/StudyMapper.xml b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/StudyMapper.xml index 01abbcf270d..e79ba8c2ae5 100644 --- a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/StudyMapper.xml +++ b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/StudyMapper.xml @@ -148,14 +148,17 @@ diff --git a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/TreatmentMapper.xml b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/TreatmentMapper.xml index a9976f44d3a..de633ab7f55 100644 --- a/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/TreatmentMapper.xml +++ b/persistence/persistence-mybatis/src/main/resources/org/cbioportal/persistence/mybatis/TreatmentMapper.xml @@ -16,6 +16,7 @@ INNER JOIN sample ON patient.INTERNAL_ID = sample.PATIENT_ID INNER JOIN cancer_study ON patient.CANCER_STUDY_ID = cancer_study.CANCER_STUDY_ID + AND clinical_event.EVENT_TYPE = 'TREATMENT' AND clinical_event_data.KEY = #{key} @@ -48,9 +49,9 @@ - + SELECT EXISTS(SELECT + * FROM clinical_event INNER JOIN clinical_event_data ON clinical_event.CLINICAL_EVENT_ID = clinical_event_data.CLINICAL_EVENT_ID @@ -58,25 +59,14 @@ INNER JOIN sample ON patient.INTERNAL_ID = sample.PATIENT_ID INNER JOIN cancer_study ON patient.CANCER_STUDY_ID = cancer_study.CANCER_STUDY_ID - AND clinical_event_data.KEY = #{key} + AND clinical_event.EVENT_TYPE = 'TREATMENT' + AND clinical_event_data.KEY = #{key} LIMIT 1 + ) - - - + SELECT EXISTS(SELECT + * FROM clinical_event INNER JOIN clinical_event_data ON clinical_event.CLINICAL_EVENT_ID = clinical_event_data.CLINICAL_EVENT_ID @@ -85,20 +75,7 @@ INNER JOIN cancer_study ON patient.CANCER_STUDY_ID = cancer_study.CANCER_STUDY_ID AND clinical_event_data.KEY = 'SAMPLE_ID' - AND (clinical_event.EVENT_TYPE LIKE 'Sample Acquisition' OR clinical_event.EVENT_TYPE LIKE 'SPECIMEN') - - - diff --git a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/AlterationMyBatisRepositoryTest.java b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/AlterationMyBatisRepositoryTest.java index 89d7af7f85c..3ea53acf77e 100644 --- a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/AlterationMyBatisRepositoryTest.java +++ b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/AlterationMyBatisRepositoryTest.java @@ -1,7 +1,6 @@ package org.cbioportal.persistence.mybatis; import org.cbioportal.model.*; -import org.cbioportal.model.QueryElement; import org.cbioportal.model.util.Select; import org.junit.Assert; import org.junit.Before; @@ -20,7 +19,7 @@ public class AlterationMyBatisRepositoryTest { // mutation and cna events in testSql.sql - // SAMPLE_ID, ENTREZ_GENE_ID, HUGO_GENE_SYMBOL, GENETIC_PROFILE_ID, TYPE, MUTATION_TYPE, DRIVER_FILTER, DRIVER_TIERS_FILTER, PATIENT_ID, MUTATION_TYPE + // SAMPLE_ID, ENTREZ_GENE_ID, HUGO_GENE_SYMBOL, GENETIC_PROFILE_ID, TYPE, MUTATIONio_TYPE, DRIVER_FILTER, DRIVER_TIERS_FILTER, PATIENT_ID, MUTATION_TYPE // 1 207 AKT1 2 CNA -2 Putative_Driver Tier 1 TCGA-A1-A0SB germline // 2 207 AKT1 2 CNA 2 Putative_Passenger Tier 2 TCGA-A1-A0SD germline // 1 207 AKT1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 1 TCGA-A1-A0SB germline @@ -43,7 +42,8 @@ public class AlterationMyBatisRepositoryTest { // 15 57670-673 KIAA..-BRAF 13 SV Fusion TCGA-A1-A0SD somatic // 1 8031-5979 NCOA4-RET 7 SV Fusion TCGA-A1-A0SB somatic // 15 8031-5979 NCOA4-RET 13 SV Fusion TCGA-A1-A0SB somatic - // 1 7113-2078 TMPRSS2-ERG 7 SV Fusion TCGA-A1-A0SB somatic + // 15 7113-2078 TMPRSS2-ERG 7 SV Fusion TCGA-A1-A0SB somatic + // 15 8031- NCOA4- 13 SV Fusion TCGA-A1-A0SB somatic @Autowired private AlterationMyBatisRepository alterationMyBatisRepository; @@ -57,15 +57,13 @@ public class AlterationMyBatisRepositoryTest { CNA.AMP, CNA.HOMDEL )); - List sampleIdToProfileId = new ArrayList<>(); - List patientIdToProfileId = new ArrayList<>(); - - List svSampleIdToProfileId = new ArrayList<>(); - List svPatientIdToProfileId = new ArrayList<>(); + Set sampleIdToProfileId = new TreeSet<>(); + Set svSampleIdToProfileId = new TreeSet<>(); + Set patientIdToProfileId = new TreeSet<>(); + Set svPatientIdToProfileId = new TreeSet<>(); AlterationFilter alterationFilter; Select entrezGeneIds; - Select svEntrezGeneIds; @Before @@ -82,6 +80,7 @@ public void setup() { sampleIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-A0SD-01", "study_tcga_pub_gistic")); svSampleIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-A0SB-01", "study_tcga_pub_sv")); svSampleIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-A0SD-01", "study_tcga_pub_sv")); + svSampleIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-B0SO-01", "acc_tcga_sv")); patientIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-A0SB", "study_tcga_pub_mutations")); patientIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-A0SE", "study_tcga_pub_mutations")); @@ -94,6 +93,7 @@ public void setup() { patientIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-A0SD", "study_tcga_pub_gistic")); svPatientIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-A0SB", "study_tcga_pub_sv")); svPatientIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-A0SD", "study_tcga_pub_sv")); + svPatientIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-B0SO", "acc_tcga_sv")); entrezGeneIds = Select.byValues(Arrays.asList(207, 208, 672, 2064)); svEntrezGeneIds = Select.byValues(Arrays.asList(57670, 8031, 27436, 7113)); @@ -112,24 +112,24 @@ public void setup() { } @Test - public void getSampleMutationCountAllDriverAnnotationsExcluded() throws Exception { + public void getSampleMutationGeneCountAllDriverAnnotationsExcluded() throws Exception { alterationFilter.setIncludeDriver(false); alterationFilter.setIncludeVUS(false); alterationFilter.setIncludeUnknownOncogenicity(false); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new HashSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(0, result.size()); } @Test - public void getSampleMutationCountAllDriverTiersExcluded() throws Exception { + public void getSampleMutationGeneCountAllDriverTiersExcluded() throws Exception { alterationFilter.setSelectedTiers(Select.none()); alterationFilter.setIncludeUnknownTier(false); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( new TreeSet<>(sampleIdToProfileId), entrezGeneIds, alterationFilter); @@ -137,35 +137,35 @@ public void getSampleMutationCountAllDriverTiersExcluded() throws Exception { } @Test - public void getSampleMutationCountAllDriverTiersExcludedWithNullSelect() throws Exception { + public void getSampleMutationGeneCountAllDriverTiersExcludedWithNullSelect() throws Exception { alterationFilter.setSelectedTiers(null); alterationFilter.setIncludeUnknownTier(false); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(0, result.size()); } @Test - public void getSampleMutationCountAllMutationStatusExcluded() throws Exception { + public void getSampleMutationGeneCountAllMutationStatusExcluded() throws Exception { alterationFilter.setIncludeSomatic(false); alterationFilter.setIncludeGermline(false); alterationFilter.setIncludeUnknownStatus(false); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(0, result.size()); } @Test - public void getSampleMutationCount() throws Exception { + public void getSampleMutationGeneCount() throws Exception { alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); @@ -182,10 +182,10 @@ public void getSampleMutationCount() throws Exception { } @Test - public void getSampleCnaCount() throws Exception { + public void getSampleCnaGeneCount() throws Exception { alterationFilter.setMutationTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); @@ -199,9 +199,9 @@ public void getSampleCnaCount() throws Exception { } @Test - public void getSampleMutationAndCnaCount() throws Exception { - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + public void getSampleMutationAndCnaGeneCount() throws Exception { + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); @@ -220,24 +220,24 @@ public void getSampleMutationAndCnaCount() throws Exception { @Test public void whenSampleNotProfiledForCNA() throws Exception { - List sampleIdToProfileId = new ArrayList<>(); + Set sampleIdToProfileId = new TreeSet<>(); // Sample is not profiled for mutations and not cna sampleIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-A0SE-01", "study_tcga_pub_gistic")); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(0, result.size()); } @Test - public void getPatientCnaCountAllDriverAnnotationsExcluded() throws Exception { + public void getPatientCnaGeneCountAllDriverAnnotationsExcluded() throws Exception { alterationFilter.setIncludeDriver(false); alterationFilter.setIncludeVUS(false); alterationFilter.setIncludeUnknownOncogenicity(false); alterationFilter.setMutationTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -245,11 +245,11 @@ public void getPatientCnaCountAllDriverAnnotationsExcluded() throws Exception { } @Test - public void getPatientCnaCountAllDriverTiersExcluded() throws Exception { + public void getPatientCnaGeneCountAllDriverTiersExcluded() throws Exception { alterationFilter.setSelectedTiers(Select.none()); alterationFilter.setIncludeUnknownTier(false); alterationFilter.setMutationTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -257,11 +257,11 @@ public void getPatientCnaCountAllDriverTiersExcluded() throws Exception { } @Test - public void getPatientCnaCountAllDriverTiersExcludedNullSelect() throws Exception { + public void getPatientCnaGeneCountAllDriverTiersExcludedNullSelect() throws Exception { alterationFilter.setSelectedTiers(null); alterationFilter.setIncludeUnknownTier(false); alterationFilter.setMutationTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -269,9 +269,9 @@ public void getPatientCnaCountAllDriverTiersExcludedNullSelect() throws Exceptio } @Test - public void getPatientCnaCount() throws Exception { + public void getPatientCnaGeneCount() throws Exception { alterationFilter.setMutationTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -288,14 +288,14 @@ public void getPatientCnaCount() throws Exception { } @Test - public void getSampleCnaCountLegacy() throws Exception { + public void getSampleCnaGeneCountLegacy() throws Exception { // FIXME: the CnaCountLegacy endpoint is different from the AlterationCount endpoint // because it returns a single additional value 'cytoband'. It would make sense to // harmonize these endpoints (both or none return 'cytoband') and use the AlterationCount // endpoint for all counts. Let's discuss... - List result = alterationMyBatisRepository.getSampleCnaCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); @@ -309,13 +309,13 @@ public void getSampleCnaCountLegacy() throws Exception { } @Test - public void getPatientCnaCountLegacy() throws Exception { + public void getPatientCnaGeneCountLegacy() throws Exception { // FIXME: the CnaCountLegacy endpoint is different from the AlterationCount endpoint // because it returns a single additional value 'cytoband'. It would make sense to // harmonize these endpoints (both or none return 'cytoband') and use the AlterationCount // endpoint for all counts. Let's discuss... - List result = alterationMyBatisRepository.getPatientCnaCounts( + List result = alterationMyBatisRepository.getPatientCnaGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -332,12 +332,12 @@ public void getPatientCnaCountLegacy() throws Exception { } @Test - public void getSampleAlterationCountsReturnsZeroForMutationsAndCnaSelectorsInNone() { + public void getSampleAlterationGeneCountsReturnsZeroForMutationsAndCnaSelectorsInNone() { alterationFilter.setCnaTypeSelect(Select.none()); alterationFilter.setMutationTypeSelect(Select.none()); alterationFilter.setStructuralVariants(false); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); @@ -345,11 +345,11 @@ public void getSampleAlterationCountsReturnsZeroForMutationsAndCnaSelectorsInNon } @Test - public void getSampleAlterationCountsReturnsAllForMutationsAndCnaSelectorsInAll() { + public void getSampleAlterationGeneCountsReturnsAllForMutationsAndCnaSelectorsInAll() { alterationFilter.setCnaTypeSelect(Select.all()); alterationFilter.setMutationTypeSelect(Select.all()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); @@ -357,32 +357,32 @@ public void getSampleAlterationCountsReturnsAllForMutationsAndCnaSelectorsInAll( } @Test - public void getSampleCountNullIds() throws Exception { - List result = alterationMyBatisRepository.getSampleAlterationCounts( + public void getSampleGeneCountNullIds() throws Exception { + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( null, entrezGeneIds, new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getPatientCountNullIds() throws Exception { - List result = alterationMyBatisRepository.getPatientAlterationCounts( + public void getPatientGeneCountNullIds() throws Exception { + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( null, entrezGeneIds, new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getSampleCnaCountNullIds() throws Exception { - List result = alterationMyBatisRepository.getSampleCnaCounts( + public void getSampleCnaGeneCountNullIds() throws Exception { + List result = alterationMyBatisRepository.getSampleCnaGeneCounts( null, entrezGeneIds, new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getSampleCountIncludeOnlyDriver() throws Exception { + public void getSampleGeneCountIncludeOnlyDriver() throws Exception { alterationFilter.setIncludeVUS(false); alterationFilter.setIncludeUnknownOncogenicity(false); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); @@ -396,11 +396,11 @@ public void getSampleCountIncludeOnlyDriver() throws Exception { } @Test - public void getSampleCountIncludeOnlyVus() throws Exception { + public void getSampleGeneCountIncludeOnlyVus() throws Exception { alterationFilter.setIncludeDriver(false); alterationFilter.setIncludeUnknownOncogenicity(false); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); @@ -417,11 +417,11 @@ public void getSampleCountIncludeOnlyVus() throws Exception { } @Test - public void getSampleCountIncludeOnlyUnknownOncogenicity() throws Exception { + public void getSampleGeneCountIncludeOnlyUnknownOncogenicity() throws Exception { alterationFilter.setIncludeDriver(false); alterationFilter.setIncludeVUS(false); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); @@ -432,12 +432,12 @@ public void getSampleCountIncludeOnlyUnknownOncogenicity() throws Exception { } @Test - public void getSampleCountIncludeOnlyTiers() throws Exception { + public void getSampleGeneCountIncludeOnlyTiers() throws Exception { // All 'Tier 2' tiers are forced to be interpreted as driver events alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Tier 2"))); alterationFilter.setIncludeUnknownTier(false); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); @@ -451,10 +451,10 @@ public void getSampleCountIncludeOnlyTiers() throws Exception { } @Test - public void getSampleCountIncludeUnknownTier() throws Exception { + public void getSampleGeneCountIncludeUnknownTier() throws Exception { alterationFilter.setSelectedTiers(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); @@ -465,8 +465,8 @@ public void getSampleCountIncludeUnknownTier() throws Exception { } @Test - public void getPatientMutationAndCnaCount() throws Exception { - List result = alterationMyBatisRepository.getPatientAlterationCounts( + public void getPatientMutationAndCnaGeneCount() throws Exception { + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -486,11 +486,11 @@ public void getPatientMutationAndCnaCount() throws Exception { } @Test - public void getPatientMutationCountIncludeOnlyGermline() throws Exception { + public void getPatientMutationGeneCountIncludeOnlyGermline() throws Exception { alterationFilter.setIncludeSomatic(false); alterationFilter.setIncludeUnknownStatus(false); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -508,11 +508,11 @@ public void getPatientMutationCountIncludeOnlyGermline() throws Exception { } @Test - public void getPatientMutationCountIncludeOnlySomatic() throws Exception { + public void getPatientMutationGeneCountIncludeOnlySomatic() throws Exception { alterationFilter.setIncludeGermline(false); alterationFilter.setIncludeUnknownStatus(false); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -521,11 +521,11 @@ public void getPatientMutationCountIncludeOnlySomatic() throws Exception { } @Test - public void getPatientMutationCountIncludeOnlyUnknownStatus() throws Exception { + public void getPatientMutationGeneCountIncludeOnlyUnknownStatus() throws Exception { alterationFilter.setIncludeGermline(false); alterationFilter.setIncludeSomatic(false); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -534,10 +534,10 @@ public void getPatientMutationCountIncludeOnlyUnknownStatus() throws Exception { } @Test - public void getPatientCountIncludeOnlyDriver() throws Exception { + public void getPatientGeneCountIncludeOnlyDriver() throws Exception { alterationFilter.setIncludeVUS(false); alterationFilter.setIncludeUnknownOncogenicity(false); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -552,10 +552,10 @@ public void getPatientCountIncludeOnlyDriver() throws Exception { } @Test - public void getPatientCountIncludeOnlyVUS() throws Exception { + public void getPatientGeneCountIncludeOnlyVUS() throws Exception { alterationFilter.setIncludeDriver(false); alterationFilter.setIncludeUnknownOncogenicity(false); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -573,10 +573,10 @@ public void getPatientCountIncludeOnlyVUS() throws Exception { } @Test - public void getPatientCountIncludeOnlyUnknownOncogenicity() throws Exception { + public void getPatientGeneCountIncludeOnlyUnknownOncogenicity() throws Exception { alterationFilter.setIncludeDriver(false); alterationFilter.setIncludeVUS(false); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -588,11 +588,11 @@ public void getPatientCountIncludeOnlyUnknownOncogenicity() throws Exception { } @Test - public void getPatientCountIncludeOnlyTiers() throws Exception { + public void getPatientGeneCountIncludeOnlyTiers() throws Exception { // All 'Tier 2' tiers are forced to be interpreted as driver events alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Tier 2"))); alterationFilter.setIncludeUnknownTier(false); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -607,9 +607,9 @@ public void getPatientCountIncludeOnlyTiers() throws Exception { } @Test - public void getPatientCountIncludeUnknownTier() throws Exception { + public void getPatientGeneCountIncludeUnknownTier() throws Exception { alterationFilter.setSelectedTiers(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); @@ -621,10 +621,10 @@ public void getPatientCountIncludeUnknownTier() throws Exception { } @Test - public void getSampleCnaCountLegacyOnlyDriver() throws Exception { + public void getSampleCnaGeneCountLegacyOnlyDriver() throws Exception { alterationFilter.setIncludeVUS(false); alterationFilter.setIncludeUnknownOncogenicity(false); - List result = alterationMyBatisRepository.getSampleCnaCounts(new TreeSet<>(sampleIdToProfileId), entrezGeneIds, alterationFilter); + List result = alterationMyBatisRepository.getSampleCnaGeneCounts(sampleIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(1, result.size()); AlterationCountByGene result207 = result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); @@ -633,10 +633,10 @@ public void getSampleCnaCountLegacyOnlyDriver() throws Exception { } @Test - public void getSampleCnaCountLegacyOnlyVUS() throws Exception { + public void getSampleCnaGeneCountLegacyOnlyVUS() throws Exception { alterationFilter.setIncludeDriver(false); alterationFilter.setIncludeUnknownOncogenicity(false); - List result = alterationMyBatisRepository.getSampleCnaCounts(new TreeSet<>(sampleIdToProfileId), entrezGeneIds, alterationFilter); + List result = alterationMyBatisRepository.getSampleCnaGeneCounts(sampleIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(1, result.size()); AlterationCountByGene result207 = result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); @@ -645,11 +645,11 @@ public void getSampleCnaCountLegacyOnlyVUS() throws Exception { } @Test - public void getSampleCnaCountLegacyOnlyUnknownOncogenicity() throws Exception { + public void getSampleCnaGeneCountLegacyOnlyUnknownOncogenicity() throws Exception { alterationFilter.setIncludeDriver(false); alterationFilter.setIncludeVUS(false); - List result = alterationMyBatisRepository.getSampleCnaCounts( - new TreeSet<>(sampleIdToProfileId), entrezGeneIds, alterationFilter); + List result = alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(1, result.size()); AlterationCountByGene result208 = result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); @@ -658,10 +658,10 @@ public void getSampleCnaCountLegacyOnlyUnknownOncogenicity() throws Exception { } @Test - public void getSampleCnaCountLegacyOnlyUnknownTier() throws Exception { + public void getSampleCnaGeneCountLegacyOnlyUnknownTier() throws Exception { alterationFilter.setSelectedTiers(Select.none()); - List result = alterationMyBatisRepository.getSampleCnaCounts( - new TreeSet<>(sampleIdToProfileId), entrezGeneIds, alterationFilter); + List result = alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(1, result.size()); AlterationCountByGene result208 = result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); @@ -670,12 +670,12 @@ public void getSampleCnaCountLegacyOnlyUnknownTier() throws Exception { } @Test - public void getSampleCnaCountLegacyOnlyTier2() throws Exception { + public void getSampleCnaGeneCountLegacyOnlyTier2() throws Exception { // All 'Tier 2' tiers are forced to be interpreted as driver events alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Tier 2"))); alterationFilter.setIncludeUnknownTier(false); - List result = alterationMyBatisRepository.getSampleCnaCounts( - new TreeSet<>(sampleIdToProfileId), entrezGeneIds, alterationFilter); + List result = alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(1, result.size()); AlterationCountByGene result207 = result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); @@ -684,10 +684,10 @@ public void getSampleCnaCountLegacyOnlyTier2() throws Exception { } @Test - public void getPatientCnaCountLegacyOnlyDriver() throws Exception { + public void getPatientCnaGeneCountLegacyOnlyDriver() throws Exception { alterationFilter.setIncludeVUS(false); alterationFilter.setIncludeUnknownOncogenicity(false); - List result = alterationMyBatisRepository.getPatientCnaCounts( + List result = alterationMyBatisRepository.getPatientCnaGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(1, result.size()); @@ -697,10 +697,10 @@ public void getPatientCnaCountLegacyOnlyDriver() throws Exception { } @Test - public void getPatientCnaCountLegacyOnlyVUS() throws Exception { + public void getPatientCnaGeneCountLegacyOnlyVUS() throws Exception { alterationFilter.setIncludeDriver(false); alterationFilter.setIncludeUnknownOncogenicity(false); - List result = alterationMyBatisRepository.getPatientCnaCounts( + List result = alterationMyBatisRepository.getPatientCnaGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(1, result.size()); @@ -710,10 +710,10 @@ public void getPatientCnaCountLegacyOnlyVUS() throws Exception { } @Test - public void getPatientCnaCountLegacyOnlyUnknownOncogenicity() throws Exception { + public void getPatientCnaGeneCountLegacyOnlyUnknownOncogenicity() throws Exception { alterationFilter.setIncludeDriver(false); alterationFilter.setIncludeVUS(false); - List result = alterationMyBatisRepository.getPatientCnaCounts( + List result = alterationMyBatisRepository.getPatientCnaGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(1, result.size()); @@ -723,9 +723,9 @@ public void getPatientCnaCountLegacyOnlyUnknownOncogenicity() throws Exception { } @Test - public void getPatientCnaCountLegacyOnlyUnknownTier() throws Exception { + public void getPatientCnaGeneCountLegacyOnlyUnknownTier() throws Exception { alterationFilter.setSelectedTiers(Select.none()); - List result = alterationMyBatisRepository.getPatientCnaCounts( + List result = alterationMyBatisRepository.getPatientCnaGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(1, result.size()); @@ -735,12 +735,12 @@ public void getPatientCnaCountLegacyOnlyUnknownTier() throws Exception { } @Test - public void getPatientCnaCountLegacyOnlyTier2() throws Exception { + public void getPatientCnaGeneCountLegacyOnlyTier2() throws Exception { // All 'Tier 2' tiers are forced to be interpreted as driver events alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Tier 2"))); alterationFilter.setIncludeUnknownTier(false); alterationFilter.setSelectedTiers( Select.byValues(Arrays.asList("Tier 2"))); - List result = alterationMyBatisRepository.getPatientCnaCounts( + List result = alterationMyBatisRepository.getPatientCnaGeneCounts( patientIdToProfileId, entrezGeneIds, alterationFilter); Assert.assertEquals(1, result.size()); @@ -751,92 +751,92 @@ public void getPatientCnaCountLegacyOnlyTier2() throws Exception { @Test - public void getPatientCnaCountNullIds() throws Exception { - List result = alterationMyBatisRepository.getPatientCnaCounts( + public void getPatientCnaGeneCountNullIds() throws Exception { + List result = alterationMyBatisRepository.getPatientCnaGeneCounts( null, entrezGeneIds, new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getSampleCountNullEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), null, new AlterationFilter()); + public void getSampleGeneCountNullEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, null, new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getSampleCountEmptyEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), Select.none(), new AlterationFilter()); + public void getSampleGeneCountEmptyEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, Select.none(), new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getSampleCountAllEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(sampleIdToProfileId), Select.all(), new AlterationFilter()); + public void getSampleGeneCountAllEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, Select.all(), new AlterationFilter()); Assert.assertEquals(3, result.size()); } @Test - public void getPatientCountNullEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getPatientAlterationCounts( + public void getPatientGeneCountNullEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, null, new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getPatientCountEmptyEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getPatientAlterationCounts( + public void getPatientGeneCountEmptyEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, Select.none(), new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getPatientCountAllEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getPatientAlterationCounts( + public void getPatientGeneCountAllEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( patientIdToProfileId, Select.all(), new AlterationFilter()); Assert.assertEquals(3, result.size()); } @Test - public void getSampleCnaCountNullEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getSampleCnaCounts( - new TreeSet<>(sampleIdToProfileId), null, new AlterationFilter()); + public void getSampleCnaGeneCountNullEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, null, new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getSampleCnaCountEmptyEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getSampleCnaCounts( - new TreeSet<>(sampleIdToProfileId), Select.none(), new AlterationFilter()); + public void getSampleCnaGeneCountEmptyEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, Select.none(), new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getSampleCnaCountAllEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getSampleCnaCounts( - new TreeSet<>(sampleIdToProfileId), Select.all(), new AlterationFilter()); + public void getSampleCnaGeneCountAllEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, Select.all(), new AlterationFilter()); Assert.assertEquals(3, result.size()); } @Test - public void getPatientCnaCountNullEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getPatientCnaCounts( + public void getPatientCnaGeneCountNullEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getPatientCnaGeneCounts( patientIdToProfileId, null, new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getPatientCnaCountEmptyEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getPatientCnaCounts( + public void getPatientCnaGeneCountEmptyEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getPatientCnaGeneCounts( patientIdToProfileId, Select.none(), new AlterationFilter()); Assert.assertEquals(0, result.size()); } @Test - public void getPatientCnaCountAllEntrezGeneIds() throws Exception { - List result = alterationMyBatisRepository.getPatientCnaCounts( + public void getPatientCnaGeneCountAllEntrezGeneIds() throws Exception { + List result = alterationMyBatisRepository.getPatientCnaGeneCounts( patientIdToProfileId, Select.all(), new AlterationFilter()); Assert.assertEquals(3, result.size()); } @@ -850,8 +850,8 @@ public void getSampleStructuralVariantCountAllStructuralVariantStatusExcluded() alterationFilter.setStructuralVariants(true); alterationFilter.setMutationTypeSelect(Select.none()); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(svSampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + svSampleIdToProfileId, svEntrezGeneIds, alterationFilter); Assert.assertEquals(0, result.size()); @@ -862,8 +862,8 @@ public void getSampleStructuralVariantCountAllStructuralVariantStatusIncluded() alterationFilter.setStructuralVariants(true); alterationFilter.setMutationTypeSelect(Select.none()); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(svSampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + svSampleIdToProfileId, svEntrezGeneIds, alterationFilter); Assert.assertEquals(4, result.size()); @@ -876,19 +876,22 @@ public void getSampleStructuralVariantCountIncludeOnlyGermline() throws Exceptio alterationFilter.setStructuralVariants(true); alterationFilter.setMutationTypeSelect(Select.none()); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(svSampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + svSampleIdToProfileId, svEntrezGeneIds, alterationFilter); // two structural variants in testSql.sql are germline mutations AlterationCountByGene result57670 = result.stream().filter(r -> r.getEntrezGeneId() == 57670).findFirst().get(); AlterationCountByGene result27436 = result.stream().filter(r -> r.getEntrezGeneId() == 27436).findFirst().get(); - Assert.assertEquals(2, result.size()); + AlterationCountByGene result7113 = result.stream().filter(r -> r.getEntrezGeneId() == 7113).findFirst().get(); + Assert.assertEquals(3, result.size()); Assert.assertEquals((Integer) 1, result57670.getTotalCount()); Assert.assertEquals((Integer) 1, result57670.getNumberOfAlteredCases()); Assert.assertEquals((Integer) 1, result27436.getTotalCount()); Assert.assertEquals((Integer) 1, result27436.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result7113.getTotalCount()); + Assert.assertEquals((Integer) 1, result7113.getNumberOfAlteredCases()); } @Test @@ -898,8 +901,8 @@ public void getSampleStructuralVariantCountIncludeOnlySomatic() throws Exception alterationFilter.setStructuralVariants(true); alterationFilter.setMutationTypeSelect(Select.none()); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(svSampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + svSampleIdToProfileId, svEntrezGeneIds, alterationFilter); Assert.assertEquals(4, result.size()); @@ -908,10 +911,10 @@ public void getSampleStructuralVariantCountIncludeOnlySomatic() throws Exception AlterationCountByGene result8031 = result.stream().filter(r -> r.getEntrezGeneId() == 8031).findFirst().get(); AlterationCountByGene result27436 = result.stream().filter(r -> r.getEntrezGeneId() == 27436).findFirst().get(); AlterationCountByGene result7113 = result.stream().filter(r -> r.getEntrezGeneId() == 7113).findFirst().get(); - Assert.assertEquals((Integer) 2, result57670.getTotalCount()); - Assert.assertEquals((Integer) 2, result57670.getNumberOfAlteredCases()); - Assert.assertEquals((Integer) 1, result8031.getTotalCount()); - Assert.assertEquals((Integer) 1, result8031.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 3, result57670.getTotalCount()); + Assert.assertEquals((Integer) 3, result57670.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 3, result8031.getTotalCount()); + Assert.assertEquals((Integer) 2, result8031.getNumberOfAlteredCases()); Assert.assertEquals((Integer) 1, result27436.getTotalCount()); Assert.assertEquals((Integer) 1, result27436.getNumberOfAlteredCases()); Assert.assertEquals((Integer) 1, result7113.getTotalCount()); @@ -925,8 +928,8 @@ public void getSampleStructuralVariantCountIncludeOnlyUnknownStatus() throws Exc alterationFilter.setStructuralVariants(true); alterationFilter.setMutationTypeSelect(Select.none()); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getSampleAlterationCounts( - new TreeSet<>(svSampleIdToProfileId), + List result = alterationMyBatisRepository.getSampleAlterationGeneCounts( + svSampleIdToProfileId, svEntrezGeneIds, alterationFilter); Assert.assertEquals(0, result.size()); @@ -941,7 +944,7 @@ public void getPatientStructuralVariantCountAllStructuralVariantStatusExcluded() alterationFilter.setStructuralVariants(true); alterationFilter.setMutationTypeSelect(Select.none()); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( svPatientIdToProfileId, svEntrezGeneIds, alterationFilter); @@ -953,7 +956,7 @@ public void getPatientStructuralVariantCountAllStructuralVariantStatusIncluded() alterationFilter.setStructuralVariants(true); alterationFilter.setMutationTypeSelect(Select.none()); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( svPatientIdToProfileId, svEntrezGeneIds, alterationFilter); @@ -967,19 +970,22 @@ public void getPatientStructuralVariantCountIncludeOnlyGermline() throws Excepti alterationFilter.setStructuralVariants(true); alterationFilter.setMutationTypeSelect(Select.none()); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( svPatientIdToProfileId, svEntrezGeneIds, alterationFilter); // two structural variants in testSql.sql are germline mutations - Assert.assertEquals(2, result.size()); + Assert.assertEquals(3, result.size()); AlterationCountByGene result57670 = result.stream().filter(r -> r.getEntrezGeneId() == 57670).findFirst().get(); AlterationCountByGene result27436 = result.stream().filter(r -> r.getEntrezGeneId() == 27436).findFirst().get(); + AlterationCountByGene result7113 = result.stream().filter(r -> r.getEntrezGeneId() == 7113).findFirst().get(); Assert.assertEquals((Integer) 1, result57670.getTotalCount()); Assert.assertEquals((Integer) 1, result57670.getNumberOfAlteredCases()); Assert.assertEquals((Integer) 1, result27436.getTotalCount()); Assert.assertEquals((Integer) 1, result27436.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result7113.getTotalCount()); + Assert.assertEquals((Integer) 1, result7113.getNumberOfAlteredCases()); } @Test @@ -989,7 +995,7 @@ public void getPatientStructuralVariantCountIncludeOnlySomatic() throws Exceptio alterationFilter.setStructuralVariants(true); alterationFilter.setMutationTypeSelect(Select.none()); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( svPatientIdToProfileId, svEntrezGeneIds, alterationFilter); @@ -999,10 +1005,10 @@ public void getPatientStructuralVariantCountIncludeOnlySomatic() throws Exceptio AlterationCountByGene result8031 = result.stream().filter(r -> r.getEntrezGeneId() == 8031).findFirst().get(); AlterationCountByGene result27436 = result.stream().filter(r -> r.getEntrezGeneId() == 27436).findFirst().get(); AlterationCountByGene result7113 = result.stream().filter(r -> r.getEntrezGeneId() == 7113).findFirst().get(); - Assert.assertEquals((Integer) 2, result57670.getTotalCount()); - Assert.assertEquals((Integer) 2, result57670.getNumberOfAlteredCases()); - Assert.assertEquals((Integer) 1, result8031.getTotalCount()); - Assert.assertEquals((Integer) 1, result8031.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 3, result57670.getTotalCount()); + Assert.assertEquals((Integer) 3, result57670.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 3, result8031.getTotalCount()); + Assert.assertEquals((Integer) 2, result8031.getNumberOfAlteredCases()); Assert.assertEquals((Integer) 1, result27436.getTotalCount()); Assert.assertEquals((Integer) 1, result27436.getNumberOfAlteredCases()); Assert.assertEquals((Integer) 1, result7113.getTotalCount()); @@ -1016,11 +1022,158 @@ public void getPatientStructuralVariantCountIncludeOnlyUnknownStatus() throws Ex alterationFilter.setStructuralVariants(true); alterationFilter.setMutationTypeSelect(Select.none()); alterationFilter.setCnaTypeSelect(Select.none()); - List result = alterationMyBatisRepository.getPatientAlterationCounts( + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( + svPatientIdToProfileId, + svEntrezGeneIds, + alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientStructuralVariantCountIncludeCustomDriverAnnotationsIncludeUnknown() throws Exception { + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Class 2"))); + alterationFilter.setIncludeUnknownTier(true); + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( + svPatientIdToProfileId, + svEntrezGeneIds, + alterationFilter + ); + Assert.assertEquals(4, result.size()); + } + + @Test + public void getPatientStructuralVariantCountIncludeCustomDriverAnnotationsExcludeUnknown() throws Exception { + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Class 2"))); + alterationFilter.setIncludeUnknownTier(false); + List result = alterationMyBatisRepository.getPatientAlterationGeneCounts( svPatientIdToProfileId, svEntrezGeneIds, + alterationFilter + ); + Assert.assertEquals(1, result.size()); + } + @Test + public void getSampleStructuralVariantCount() throws Exception { + List result = alterationMyBatisRepository.getSampleStructuralVariantCounts( + svSampleIdToProfileId, + alterationFilter); + + // Should be one KIAA154-BRAF, one NCOA4-RET and one NCOA4-null + Assert.assertEquals(5, result.size()); + AlterationCountByStructuralVariant resultEmlAlk = findStructVarCount("EML4", "ALK", result); + AlterationCountByStructuralVariant resultKiaaBraf= findStructVarCount("KIAA1549", "BRAF", result); + AlterationCountByStructuralVariant resultTmprsErg = findStructVarCount("TMPRSS2", "ERG", result); + AlterationCountByStructuralVariant resultNcoRet = findStructVarCount("NCOA4", "RET", result); + AlterationCountByStructuralVariant resultNcoNull = findStructVarCount("NCOA4", null, result); + Assert.assertEquals((Integer) 2, resultEmlAlk.getTotalCount()); + Assert.assertEquals((Integer) 2, resultEmlAlk.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 4, resultKiaaBraf.getTotalCount()); + Assert.assertEquals((Integer) 3, resultKiaaBraf.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, resultNcoRet.getTotalCount()); + Assert.assertEquals((Integer) 2, resultNcoRet.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, resultNcoNull.getTotalCount()); + Assert.assertEquals((Integer) 1, resultNcoNull.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, resultTmprsErg.getTotalCount()); + Assert.assertEquals((Integer) 2, resultTmprsErg.getNumberOfAlteredCases()); + } + + @Test + public void getSampleStructuralVariantCountAllSvStatusExcluded() throws Exception { + + // Note: 'NA' for SV status is not allowed as per file-formats.md + alterationFilter.setIncludeSomatic(false); + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeUnknownStatus(false); + List result = alterationMyBatisRepository.getSampleStructuralVariantCounts( + sampleIdToProfileId, alterationFilter); + Assert.assertEquals(0, result.size()); } + + @Test + public void getSampleStructuralVariantCountSomaticSvStatusExcluded() throws Exception { + + // Note: 'NA' for SV status is not allowed as per file-formats.md + alterationFilter.setIncludeSomatic(false); + alterationFilter.setIncludeUnknownStatus(false); + List result = alterationMyBatisRepository.getSampleStructuralVariantCounts( + svSampleIdToProfileId, + alterationFilter); + + Assert.assertEquals(3, result.size()); + AlterationCountByStructuralVariant resultKiaaBraf= findStructVarCount("KIAA1549", "BRAF", result); + AlterationCountByStructuralVariant resultEmlAlk = findStructVarCount("EML4", "ALK", result); + AlterationCountByStructuralVariant resultTmprsErg = findStructVarCount("TMPRSS2", "ERG", result); + Assert.assertEquals((Integer) 1, resultKiaaBraf.getTotalCount()); + Assert.assertEquals((Integer) 1, resultKiaaBraf.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, resultEmlAlk.getTotalCount()); + Assert.assertEquals((Integer) 1, resultEmlAlk.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, resultTmprsErg.getTotalCount()); + Assert.assertEquals((Integer) 1, resultTmprsErg.getNumberOfAlteredCases()); + } + + @Test + public void getSampleStructuralVariantCountGermlineSvStatusExcluded() throws Exception { + // Note: 'NA' for SV status is not allowed as per file-formats.md + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeUnknownStatus(false); + List result = alterationMyBatisRepository.getSampleStructuralVariantCounts( + svSampleIdToProfileId, + alterationFilter); + + Assert.assertEquals(5, result.size()); + AlterationCountByStructuralVariant resultEmlAlk = findStructVarCount("EML4", "ALK", result); + AlterationCountByStructuralVariant resultKiaaBraf= findStructVarCount("KIAA1549", "BRAF", result); + AlterationCountByStructuralVariant resultTmprsErg = findStructVarCount("TMPRSS2", "ERG", result); + AlterationCountByStructuralVariant resultNcoRet = findStructVarCount("NCOA4", "RET", result); + AlterationCountByStructuralVariant resultNcoNull = findStructVarCount("NCOA4", null, result); + Assert.assertEquals((Integer) 1, resultEmlAlk.getTotalCount()); + Assert.assertEquals((Integer) 1, resultEmlAlk.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 3, resultKiaaBraf.getTotalCount()); + Assert.assertEquals((Integer) 3, resultKiaaBraf.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, resultNcoRet.getTotalCount()); + Assert.assertEquals((Integer) 2, resultNcoRet.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, resultNcoNull.getTotalCount()); + Assert.assertEquals((Integer) 1, resultNcoNull.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, resultTmprsErg.getTotalCount()); + Assert.assertEquals((Integer) 1, resultTmprsErg.getNumberOfAlteredCases()); + } + + @Test + public void getPatientStructuralVariantCount() throws Exception { + List result = alterationMyBatisRepository.getPatientStructuralVariantCounts( + svPatientIdToProfileId, + alterationFilter); + + Assert.assertEquals(4, result.size()); + AlterationCountByStructuralVariant resultEmlAlk = findStructVarCount("EML4", "ALK", result); + AlterationCountByStructuralVariant resultKiaaBraf= findStructVarCount("KIAA1549", "BRAF", result); + AlterationCountByStructuralVariant resultTmprsErg = findStructVarCount("TMPRSS2", "ERG", result); + AlterationCountByStructuralVariant resultNcoRet = findStructVarCount("NCOA4", "RET", result); + Assert.assertEquals((Integer) 2, resultEmlAlk.getTotalCount()); + Assert.assertEquals((Integer) 2, resultEmlAlk.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 4, resultKiaaBraf.getTotalCount()); + Assert.assertEquals((Integer) 3, resultKiaaBraf.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, resultNcoRet.getTotalCount()); + Assert.assertEquals((Integer) 2, resultNcoRet.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, resultTmprsErg.getTotalCount()); + Assert.assertEquals((Integer) 2, resultTmprsErg.getNumberOfAlteredCases()); + } + + private AlterationCountByStructuralVariant findStructVarCount(String gene1HugoSymbol, + String gene2HugoSymbol, + List counts) { + return counts.stream().filter( + c -> ((c.getGene1HugoGeneSymbol() == null && gene1HugoSymbol == null) || (c.getGene1HugoGeneSymbol() != null && c.getGene1HugoGeneSymbol().equals(gene1HugoSymbol))) + && ((c.getGene2HugoGeneSymbol() == null && gene2HugoSymbol == null) || (c.getGene2HugoGeneSymbol() != null && c.getGene2HugoGeneSymbol().equals(gene2HugoSymbol))) + ).findFirst().get(); + } } diff --git a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/ClinicalDataMyBatisRepositoryTest.java b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/ClinicalDataMyBatisRepositoryTest.java index ded95f04cf3..406e830c8fb 100644 --- a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/ClinicalDataMyBatisRepositoryTest.java +++ b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/ClinicalDataMyBatisRepositoryTest.java @@ -354,9 +354,9 @@ public void fetchClinicalDataNullAttributeSummaryProjection() { @Test public void fetchClinicalSampleDataClinicalTabPagingSuccess() { - List resultFirstPage = clinicalDataMyBatisRepository.fetchSampleClinicalDataClinicalTable(studyIds, + List resultFirstPage = clinicalDataMyBatisRepository.fetchSampleClinicalTable(studyIds, sampleIds, 1, 0, noSearch, noSort, "DESC"); - List resultSecondPage = clinicalDataMyBatisRepository.fetchSampleClinicalDataClinicalTable(studyIds, + List resultSecondPage = clinicalDataMyBatisRepository.fetchSampleClinicalTable(studyIds, sampleIds, 1, 1, noSearch, noSort, "DESC"); Assert.assertEquals(4, resultFirstPage.size()); @@ -380,7 +380,7 @@ public void fetchClinicalSampleDataClinicalTabPagingSuccess() { public void fetchClinicalSampleDataClinicalTablePagingHandleNoneExistingPage() { // There are only two patients in total. The second page (index 1) with pageSize 2 does not refer to any records. - List resultNonExistingPage = clinicalDataMyBatisRepository.fetchSampleClinicalDataClinicalTable( + List resultNonExistingPage = clinicalDataMyBatisRepository.fetchSampleClinicalTable( studyIds, sampleIds, 2, 1, noSearch, noSort, "DESC"); Assert.assertEquals(0, resultNonExistingPage.size()); @@ -389,7 +389,7 @@ public void fetchClinicalSampleDataClinicalTablePagingHandleNoneExistingPage() { @Test public void fetchClinicalSampleDataClinicalTabSearchTermSuccess() { - List resultSample1 = clinicalDataMyBatisRepository.fetchSampleClinicalDataClinicalTable( + List resultSample1 = clinicalDataMyBatisRepository.fetchSampleClinicalTable( studyIds, sampleIds, noPaging, noPaging, "5C631CE8", noSort, "DESC"); Assert.assertEquals(4, resultSample1.size()); @@ -397,7 +397,7 @@ public void fetchClinicalSampleDataClinicalTabSearchTermSuccess() { Assert.assertEquals(1, observedSampleIds.size()); Assert.assertEquals("TCGA-A1-A0SB-01", observedSampleIds.get(0)); - List resultSample2 = clinicalDataMyBatisRepository.fetchSampleClinicalDataClinicalTable( + List resultSample2 = clinicalDataMyBatisRepository.fetchSampleClinicalTable( studyIds, sampleIds, noPaging, noPaging, "F3408556-9259", noSort, "DESC"); Assert.assertEquals(4, resultSample2.size()); @@ -409,7 +409,7 @@ public void fetchClinicalSampleDataClinicalTabSearchTermSuccess() { @Test public void fetchClinicalSampleDataEClinicalTabEmptyStringSearchTerm() { - List result = clinicalDataMyBatisRepository.fetchSampleClinicalDataClinicalTable( + List result = clinicalDataMyBatisRepository.fetchSampleClinicalTable( studyIds, sampleIds, noPaging, noPaging, "", noSort, "DESC"); Assert.assertEquals(8, result.size()); @@ -418,9 +418,9 @@ public void fetchClinicalSampleDataEClinicalTabEmptyStringSearchTerm() { @Test public void fetchClinicalSampleDataClinicalTabSortSuccess() { - List resultSortAsc = clinicalDataMyBatisRepository.fetchSampleClinicalDataClinicalTable(studyIds, + List resultSortAsc = clinicalDataMyBatisRepository.fetchSampleClinicalTable(studyIds, sampleIds, 1, 0, noSearch, "SAMPLE_TYPE", "ASC"); - List resultSortDesc = clinicalDataMyBatisRepository.fetchSampleClinicalDataClinicalTable(studyIds, + List resultSortDesc = clinicalDataMyBatisRepository.fetchSampleClinicalTable(studyIds, sampleIds, 1, 0, noSearch, "SAMPLE_TYPE", "DESC"); Assert.assertEquals(4, resultSortAsc.size()); diff --git a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/ClinicalEventMyBatisRepositoryTest.java b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/ClinicalEventMyBatisRepositoryTest.java index 1ab5ace7d1a..d44814115e9 100644 --- a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/ClinicalEventMyBatisRepositoryTest.java +++ b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/ClinicalEventMyBatisRepositoryTest.java @@ -197,18 +197,26 @@ public void getMetaClinicalEvents() throws Exception { @Test public void getSamplesOfPatientsPerEventTypeInStudy() { + List studyList = new ArrayList<>(); + studyList.add("study_tcga_pub"); + List sampleList = new ArrayList<>(); + sampleList.add("TCGA-A1-A0SB-01"); Map> result = clinicalEventMyBatisRepository - .getSamplesOfPatientsPerEventTypeInStudy(List.of("study_tcga_pub"), List.of("TCGA-A1-A0SB-01")); + .getSamplesOfPatientsPerEventTypeInStudy(studyList, sampleList); Assert.assertNotNull(result.get("STATUS")); } @Test public void getPatientsDistinctClinicalEventInStudies() { - List result = clinicalEventMyBatisRepository.getPatientsDistinctClinicalEventInStudies(List.of("study_tcga_pub"), List.of("TCGA-A1-A0SB")); + List studyList = new ArrayList<>(); + studyList.add("study_tcga_pub"); + List patientList = new ArrayList<>(); + patientList.add("TCGA-A1-A0SB"); + List result = clinicalEventMyBatisRepository.getPatientsDistinctClinicalEventInStudies(studyList, patientList); List eventTypes = result.stream().map(ClinicalEvent::getEventType).collect(Collectors.toList()); Assert.assertEquals(2, result.size()); Assert.assertTrue(eventTypes.contains("STATUS")); } -} \ No newline at end of file +} diff --git a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMyBatisRepositoryTest.java b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMyBatisRepositoryTest.java index 863504537eb..89a3fe0dbbf 100644 --- a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMyBatisRepositoryTest.java +++ b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMyBatisRepositoryTest.java @@ -27,7 +27,7 @@ @Configurable public class DiscreteCopyNumberMyBatisRepositoryTest { - // mutation and cna events in testSql.sql + // mutation, cna and struct var events in testSql.sql // SAMPLE_ID, ENTREZ_GENE_ID, HUGO_GENE_SYMBOL, GENETIC_PROFILE_ID, TYPE, MUTATION_TYPE, DRIVER_FILTER, DRIVER_TIERS_FILTER, PATIENT_ID, MUTATION_TYPE // 1 207 AKT1 2 CNA -2 Putative_Driver Tier 1 TCGA-A1-A0SB germline // 2 207 AKT1 2 CNA 2 Putative_Passenger Tier 2 TCGA-A1-A0SD germline @@ -40,6 +40,17 @@ public class DiscreteCopyNumberMyBatisRepositoryTest { // 7 672 BRCA1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 2 TCGA-A1-A0SI germline // 12 672 BRCA1 6 MUTATION Splice_Site Putative_Passenger Tier 1 TCGA-A1-A0SO germline // 13 672 BRCA1 6 MUTATION Splice_Site Putative_Driver Tier 1 TCGA-A1-A0SP germline + // 1 27436-238 EML4-ALK 7 SV Fusion TCGA-A1-A0SB germline + // 2 27436-238 EML4-ALK 7 SV Fusion TCGA-A1-A0SD somatic + // 1 57670-673 KIAA..-BRAF 7 SV Fusion TCGA-A1-A0SB somatic + // 2 57670-673 KIAA..-BRAF 7 SV Fusion TCGA-A1-A0SD germline + // 2 57670-673 KIAA..-BRAF 7 SV Fusion TCGA-A1-A0SD somatic + // 15 57670-673 KIAA..-BRAF 13 SV Fusion TCGA-A1-A0SD somatic + // 1 8031-5979 NCOA4-RET 7 SV Fusion TCGA-A1-A0SB somatic + // 15 8031-5979 NCOA4-RET 13 SV Fusion TCGA-A1-A0SB somatic + // 1 7113-2078 TMPRSS2-ERG 7 SV Fusion TCGA-A1-A0SB somatic + // 15 8031-NULL NCOA4- 13 SV Fusion TCGA-A1-A0SB somatic + @Autowired private DiscreteCopyNumberMyBatisRepository discreteCopyNumberMyBatisRepository; diff --git a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/MutationMyBatisRepositoryTest.java b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/MutationMyBatisRepositoryTest.java index b84fa1a32a6..6f13f7b9ff3 100644 --- a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/MutationMyBatisRepositoryTest.java +++ b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/MutationMyBatisRepositoryTest.java @@ -16,7 +16,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -26,7 +25,7 @@ @Configurable public class MutationMyBatisRepositoryTest { - // mutation and cna events in testSql.sql + // mutation, cna and struct var events in testSql.sql // SAMPLE_ID, ENTREZ_GENE_ID, HUGO_GENE_SYMBOL, GENETIC_PROFILE_ID, TYPE, MUTATION_TYPE, DRIVER_FILTER, DRIVER_TIERS_FILTER, PATIENT_ID, MUTATION_TYPE // 1 207 AKT1 2 CNA -2 Putative_Driver Tier 1 TCGA-A1-A0SB germline // 2 207 AKT1 2 CNA 2 Putative_Passenger Tier 2 TCGA-A1-A0SD germline @@ -39,6 +38,17 @@ public class MutationMyBatisRepositoryTest { // 7 672 BRCA1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 2 TCGA-A1-A0SI germline // 12 672 BRCA1 6 MUTATION Splice_Site Putative_Passenger Tier 1 TCGA-A1-A0SO germline // 13 672 BRCA1 6 MUTATION Splice_Site Putative_Driver Tier 1 TCGA-A1-A0SP germline + // 1 27436-238 EML4-ALK 7 SV Fusion TCGA-A1-A0SB germline + // 2 27436-238 EML4-ALK 7 SV Fusion TCGA-A1-A0SD somatic + // 1 57670-673 KIAA..-BRAF 7 SV Fusion TCGA-A1-A0SB somatic + // 2 57670-673 KIAA..-BRAF 7 SV Fusion TCGA-A1-A0SD germline + // 2 57670-673 KIAA..-BRAF 7 SV Fusion TCGA-A1-A0SD somatic + // 15 57670-673 KIAA..-BRAF 13 SV Fusion TCGA-A1-A0SD somatic + // 1 8031-5979 NCOA4-RET 7 SV Fusion TCGA-A1-A0SB somatic + // 15 8031-5979 NCOA4-RET 13 SV Fusion TCGA-A1-A0SB somatic + // 1 7113-2078 TMPRSS2-ERG 7 SV Fusion TCGA-A1-A0SB somatic + // 15 8031-NULL NCOA4- 13 SV Fusion TCGA-A1-A0SB somatic + @Autowired private MutationMyBatisRepository mutationMyBatisRepository; @@ -117,9 +127,9 @@ public void getMutationsInMolecularProfileBySampleListIdSummaryProjection() thro Assert.assertEquals("37", mutation.getNcbiBuild()); Assert.assertEquals((Integer) (-1), mutation.getNormalAltCount()); Assert.assertEquals((Integer) (-1), mutation.getNormalRefCount()); - Assert.assertEquals((Integer) 934, mutation.getOncotatorProteinPosEnd()); - Assert.assertEquals((Integer) 934, mutation.getOncotatorProteinPosStart()); - Assert.assertEquals("NM_007294", mutation.getOncotatorRefseqMrnaId()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosEnd()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosStart()); + Assert.assertEquals("NM_007294", mutation.getRefseqMrnaId()); Assert.assertEquals("Q934*", mutation.getProteinChange()); Assert.assertEquals("G", mutation.getReferenceAllele()); Assert.assertEquals((Long) 41244748L, mutation.getStartPosition()); @@ -158,9 +168,9 @@ public void getMutationsInMolecularProfileBySampleListIdAndEntrezGeneIdsSummaryP Assert.assertEquals("37", mutation.getNcbiBuild()); Assert.assertEquals((Integer) (-1), mutation.getNormalAltCount()); Assert.assertEquals((Integer) (-1), mutation.getNormalRefCount()); - Assert.assertEquals((Integer) 934, mutation.getOncotatorProteinPosEnd()); - Assert.assertEquals((Integer) 934, mutation.getOncotatorProteinPosStart()); - Assert.assertEquals("NM_007294", mutation.getOncotatorRefseqMrnaId()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosEnd()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosStart()); + Assert.assertEquals("NM_007294", mutation.getRefseqMrnaId()); Assert.assertEquals("Q934*", mutation.getProteinChange()); Assert.assertEquals("G", mutation.getReferenceAllele()); Assert.assertEquals((Long) 41244748L, mutation.getStartPosition()); @@ -192,17 +202,12 @@ public void getMutationsInMolecularProfileBySampleListIdDetailedProjection() thr Assert.assertEquals("BRCA1 truncating", mutation.getKeyword()); Assert.assertEquals("Germline", mutation.getMutationStatus()); Assert.assertEquals("Nonsense_Mutation", mutation.getMutationType()); - Assert.assertEquals("NA", mutation.getFunctionalImpactScore()); - Assert.assertEquals(new BigDecimal("0.0"), mutation.getFisValue()); - Assert.assertEquals("getma.org/?cm=var&var=hg19,17,41244748,G,A&fts=all", mutation.getLinkXvar()); - Assert.assertEquals("NA", mutation.getLinkPdb()); - Assert.assertEquals("NA", mutation.getLinkMsa()); Assert.assertEquals("37", mutation.getNcbiBuild()); Assert.assertEquals((Integer) (-1), mutation.getNormalAltCount()); Assert.assertEquals((Integer) (-1), mutation.getNormalRefCount()); - Assert.assertEquals((Integer) 934, mutation.getOncotatorProteinPosEnd()); - Assert.assertEquals((Integer) 934, mutation.getOncotatorProteinPosStart()); - Assert.assertEquals("NM_007294", mutation.getOncotatorRefseqMrnaId()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosEnd()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosStart()); + Assert.assertEquals("NM_007294", mutation.getRefseqMrnaId()); Assert.assertEquals("Q934*", mutation.getProteinChange()); Assert.assertEquals("G", mutation.getReferenceAllele()); Assert.assertEquals((Long) 41244748L, mutation.getStartPosition()); diff --git a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/StructuralVariantMyBatisRepositoryTest.java b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/StructuralVariantMyBatisRepositoryTest.java index a194b1fcda1..72f882290e4 100644 --- a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/StructuralVariantMyBatisRepositoryTest.java +++ b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/StructuralVariantMyBatisRepositoryTest.java @@ -24,10 +24,11 @@ package org.cbioportal.persistence.mybatis; import org.cbioportal.model.GeneFilterQuery; +import org.cbioportal.model.StructuralVariantFilterQuery; import org.cbioportal.model.StructuralVariant; -import org.cbioportal.model.StructuralVariantSpecialValue; import org.cbioportal.model.StructuralVariantGeneSubQuery; import org.cbioportal.model.StructuralVariantQuery; +import org.cbioportal.model.StructuralVariantSpecialValue; import org.cbioportal.model.util.Select; import org.junit.Assert; import org.junit.Before; @@ -50,6 +51,20 @@ @Configurable public class StructuralVariantMyBatisRepositoryTest { + // struct var events in testSql.sql + // SAMPLE_ID, ENTREZ_GENE_ID, HUGO_GENE_SYMBOL, GENETIC_PROFILE_ID, GENETIC PRODFILE, TYPE, MUTATION_TYPE, DRIVER_FILTER, DRIVER_TIERS_FILTER, PATIENT_ID, MUTATION_TYPE + // 1 27436-238 EML4-ALK 7 study_tcga_pub_sv SV Fusion TCGA-A1-A0SB germline + // 2 27436-238 EML4-ALK 7 study_tcga_pub_sv SV Fusion TCGA-A1-A0SD somatic + // 1 57670-673 KIAA..-BRAF 7 study_tcga_pub_sv SV Fusion TCGA-A1-A0SB somatic + // 2 57670-673 KIAA..-BRAF 7 study_tcga_pub_sv SV Fusion TCGA-A1-A0SD germline + // 2 57670-673 KIAA..-BRAF 7 study_tcga_pub_sv SV Fusion TCGA-A1-A0SD somatic + // 15 57670-673 KIAA..-BRAF 13 acc_tcga_sv SV Fusion TCGA-A1-A0SD somatic + // 1 8031-5979 NCOA4-RET 7 study_tcga_pub_sv SV Fusion TCGA-A1-A0SB somatic + // 15 8031-5979 NCOA4-RET 13 acc_tcga_sv SV Fusion TCGA-A1-A0SB somatic + // 1 7113-2078 TMPRSS2-ERG 7 study_tcga_pub_sv SV Fusion TCGA-A1-A0SB somatic + // 15 8031-NULL NCOA4- 13 acc_tcga_sv SV Fusion TCGA-A1-A0SB somatic + + @Autowired StructuralVariantMyBatisRepository structuralVariantMyBatisRepository; @@ -82,6 +97,12 @@ public void init() { includeDriver, includeVUS, includeUnknownOncogenicity, tiers, includeUnknownTier, includeGermline, includeSomatic, includeUnknownStatus); geneQueries = Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3, geneFilterQuery4); + // Only search for the KIAA1549-BRAF and EML4-ALK fusions. + structVarFilterQuery1 = new StructuralVariantFilterQuery("KIAA1549", 57670, "BRAF", 673, includeDriver, includeVUS, includeUnknownOncogenicity, tiers, includeUnknownTier, includeGermline, includeSomatic, includeUnknownStatus); + structVarFilterQuery2 = new StructuralVariantFilterQuery("EML4", 27436, "ALK", 238, includeDriver, includeVUS, includeUnknownOncogenicity, tiers, includeUnknownTier, includeGermline, includeSomatic, includeUnknownStatus); + structVarQueries = Arrays.asList(structVarFilterQuery1, structVarFilterQuery2); + structVarFilterQueryNullGene1 = new StructuralVariantFilterQuery(null, null, "BRAF", 673, includeDriver, includeVUS, includeUnknownOncogenicity, tiers, includeUnknownTier, includeGermline, includeSomatic, includeUnknownStatus); + structVarFilterQueryNullGene2 = new StructuralVariantFilterQuery("NCOA4", 8031, null, null, includeDriver, includeVUS, includeUnknownOncogenicity, tiers, includeUnknownTier, includeGermline, includeSomatic, includeUnknownStatus); } List molecularProfileIds = new ArrayList<>(); @@ -95,7 +116,13 @@ public void init() { boolean includeSomatic; boolean includeUnknownStatus; private List geneQueries; - List noStructVars = Collections.emptyList(); + List noEntrezIds = Collections.emptyList(); + private List noStructVars = Collections.emptyList(); + private List structVarQueries; + private StructuralVariantFilterQuery structVarFilterQuery1; + private StructuralVariantFilterQuery structVarFilterQuery2; + private StructuralVariantFilterQuery structVarFilterQueryNullGene1; + private StructuralVariantFilterQuery structVarFilterQueryNullGene2; @Test public void fetchStructuralVariantsNoSampleIdentifiers() { @@ -298,10 +325,8 @@ public void fetchStructuralVariantsMultiStudyWithSampleIdentifiers() throws Exce @Test public void fetchStructuralVariantsMultiStudyNoGeneIdentifiers() throws Exception { - List noEntrezGeneIds = new ArrayList<>(); List molecularProfileIds = new ArrayList<>(); List sampleIds = new ArrayList<>(); - molecularProfileIds.add("study_tcga_pub_sv"); sampleIds.add("TCGA-A1-A0SB-01"); molecularProfileIds.add("acc_tcga_sv"); @@ -309,7 +334,7 @@ public void fetchStructuralVariantsMultiStudyNoGeneIdentifiers() throws Exceptio List result = structuralVariantMyBatisRepository.fetchStructuralVariants(molecularProfileIds, - sampleIds, noEntrezGeneIds, noStructVars); + sampleIds, noEntrezIds, noStructVars); Assert.assertEquals(8, result.size()); } @@ -332,8 +357,8 @@ public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiers( .map(StructuralVariant::getAnnotation) .collect(Collectors.toList()); - Assert.assertArrayEquals(new String[] {"EML4-ALK.E6bA20.AB374362", "EML4-ALK.E6bA20.AB374362", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509", "NCOA4-RET.N7R1", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaPubVariants.toArray()); - Assert.assertArrayEquals(new String[] {"KIAA1549-BRAF.K16B10.COSF509", "NCOA4-NULL", "NCOA4-RET.N7R1", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaVariants.toArray()); + Assert.assertArrayEquals(new String[] {"EML4-ALK.E6bA20.AB374362", "EML4-ALK.E6bA20.AB374362-2", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509", "NCOA4-RET.N7R1", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals(new String[] {"KIAA1549-BRAF.K16B10.COSF509", "NCOA4-NULL", "NCOA4-RET.N7R1-2", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaVariants.toArray()); } @Test @@ -361,14 +386,14 @@ public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersE .map(StructuralVariant::getAnnotation) .collect(Collectors.toList()); - Assert.assertArrayEquals(new String[] {"EML4-ALK.E6bA20.AB374362", "EML4-ALK.E6bA20.AB374362", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509", "NCOA4-RET.N7R1", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaPubVariants.toArray()); - Assert.assertArrayEquals(new String[] {"KIAA1549-BRAF.K16B10.COSF509", "NCOA4-NULL", "NCOA4-RET.N7R1", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaVariants.toArray()); + Assert.assertArrayEquals(new String[] {"EML4-ALK.E6bA20.AB374362", "EML4-ALK.E6bA20.AB374362-2", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509", "NCOA4-RET.N7R1", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals(new String[] {"KIAA1549-BRAF.K16B10.COSF509", "NCOA4-NULL", "NCOA4-RET.N7R1-2", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaVariants.toArray()); } @Test public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersSelectUnknownOncogenicity() throws Exception { - // There is one passenger event in 'study_tcga_pub_sv', the rest is unannotated + // There is one passenger event in 'study_tcga_pub_sv', the rest is unannotatedd geneQueries.stream().forEach( q -> { q.setIncludeDriver(false); @@ -380,7 +405,7 @@ public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersS structuralVariantMyBatisRepository.fetchStructuralVariantsByGeneQueries(molecularProfileIds, sampleIds, geneQueries); - Assert.assertEquals(10, result.size()); + Assert.assertEquals(8, result.size()); List resultTcgaPubVariants = result.stream() .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) @@ -391,12 +416,12 @@ public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersS .map(StructuralVariant::getAnnotation) .collect(Collectors.toList()); - Assert.assertArrayEquals(new String[] {"EML4-ALK.E6bA20.AB374362", "EML4-ALK.E6bA20.AB374362", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509", "NCOA4-RET.N7R1", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaPubVariants.toArray()); - Assert.assertArrayEquals(new String[] {"KIAA1549-BRAF.K16B10.COSF509", "NCOA4-NULL", "NCOA4-RET.N7R1", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaVariants.toArray()); + Assert.assertArrayEquals(new String[] {"EML4-ALK.E6bA20.AB374362", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals(new String[] {"KIAA1549-BRAF.K16B10.COSF509", "NCOA4-NULL", "NCOA4-RET.N7R1-2", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaVariants.toArray()); } @Test - public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersSelectPassenger() throws Exception { + public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersExcludeUnknownOncogenicity() throws Exception { // There is one passenger event in 'study_tcga_pub_sv', the rest is unannotated @@ -460,7 +485,7 @@ public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersU structuralVariantMyBatisRepository.fetchStructuralVariantsByGeneQueries(molecularProfileIds, sampleIds, geneQueries); - Assert.assertEquals(10, result.size()); + Assert.assertEquals(8, result.size()); List resultTcgaPubVariants = result.stream() .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) @@ -471,8 +496,8 @@ public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersU .map(StructuralVariant::getAnnotation) .collect(Collectors.toList()); - Assert.assertArrayEquals(new String[] {"EML4-ALK.E6bA20.AB374362", "EML4-ALK.E6bA20.AB374362", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509", "NCOA4-RET.N7R1", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaPubVariants.toArray()); - Assert.assertArrayEquals(new String[] {"KIAA1549-BRAF.K16B10.COSF509", "NCOA4-NULL", "NCOA4-RET.N7R1", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaVariants.toArray()); + Assert.assertArrayEquals(new String[] {"EML4-ALK.E6bA20.AB374362", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals(new String[] {"KIAA1549-BRAF.K16B10.COSF509", "NCOA4-NULL", "NCOA4-RET.N7R1-2", "TMPRSS2-ERG.T1E2.COSF23.1"}, resultTcgaVariants.toArray()); } @Test @@ -489,8 +514,6 @@ public void fetchStructuralVariantsWithSingleStructuralVariantQueries() throws E new StructuralVariantGeneSubQuery(238) )); - List noEntrezIds = Collections.emptyList(); - List result = structuralVariantMyBatisRepository.fetchStructuralVariants( molecularProfileIds, @@ -505,6 +528,32 @@ public void fetchStructuralVariantsWithSingleStructuralVariantQueries() throws E Assert.assertEquals((Integer) 238, structuralVariantFirstResult.getSite2EntrezGeneId()); Assert.assertEquals("Fusion", structuralVariantFirstResult.getEventInfo()); } + + @Test + public void fetchStructuralVariantsWithStructuralVariantQueryAndGeneId() throws Exception { + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + molecularProfileIds.add("study_tcga_pub_sv"); + + List entrezGeneId = Arrays.asList(8031); + List singleStructVarQuery = new ArrayList<>(); + singleStructVarQuery.add(new StructuralVariantQuery( + new StructuralVariantGeneSubQuery(27436), + new StructuralVariantGeneSubQuery(238) + )); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariants( + molecularProfileIds, + sampleIds, + entrezGeneId, + singleStructVarQuery + ); + + Assert.assertEquals(3, result.size()); + } @Test public void fetchStructuralVariantsWithMultipleStructuralVariantQueries() throws Exception { @@ -522,7 +571,6 @@ public void fetchStructuralVariantsWithMultipleStructuralVariantQueries() throws new StructuralVariantGeneSubQuery(57670), new StructuralVariantGeneSubQuery(673) )); - List noEntrezIds = Collections.emptyList(); List result = structuralVariantMyBatisRepository.fetchStructuralVariants(molecularProfileIds, @@ -565,8 +613,6 @@ public void fetchStructuralVariantsWithMultipleStructuralVariantIdentifierWildca ); structVarQueries.add(svId2); - List noEntrezIds = Collections.emptyList(); - List result = structuralVariantMyBatisRepository.fetchStructuralVariants(molecularProfileIds, sampleIds, noEntrezIds, structVarQueries @@ -600,7 +646,6 @@ public void fetchStructuralVariantsWithMultipleStructuralVariantQueryNullQueryVa new StructuralVariantGeneSubQuery(StructuralVariantSpecialValue.NO_GENE) ); structVarQueries.add(structVarWithNull); - List noEntrezIds = Collections.emptyList(); List result = structuralVariantMyBatisRepository.fetchStructuralVariants(molecularProfileIds, @@ -612,5 +657,125 @@ public void fetchStructuralVariantsWithMultipleStructuralVariantQueryNullQueryVa Assert.assertEquals("ENST00000340058_NULL", result.get(0).getSite2EnsemblTranscriptId()); } + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesAll() throws Exception { + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries(molecularProfileIds, + sampleIds, structVarQueries); + + Assert.assertEquals(6, result.size()); + + List resultTcgaPubVariants = result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + List resultTcgaVariants = result.stream() + .filter(s -> "acc_tcga_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals(new String[] {"EML4-ALK.E6bA20.AB374362", "EML4-ALK.E6bA20.AB374362-2", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509"}, resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals(new String[] {"KIAA1549-BRAF.K16B10.COSF509"}, resultTcgaVariants.toArray()); + } + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesNoGermline() throws Exception { + + structVarFilterQuery1.setIncludeGermline(false); + structVarFilterQuery2.setIncludeGermline(false); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries(molecularProfileIds, + sampleIds, structVarQueries); + + Assert.assertEquals(4, result.size()); + + List resultTcgaPubVariants = result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + List resultTcgaVariants = result.stream() + .filter(s -> "acc_tcga_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals(new String[] {"EML4-ALK.E6bA20.AB374362-2", "KIAA1549-BRAF.K16B10.COSF509", "KIAA1549-BRAF.K16B10.COSF509"}, resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals(new String[] {"KIAA1549-BRAF.K16B10.COSF509"}, resultTcgaVariants.toArray()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesNoSomatic() throws Exception { + + structVarFilterQuery1.setIncludeSomatic(false); + structVarFilterQuery2.setIncludeSomatic(false); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries(molecularProfileIds, + sampleIds, structVarQueries); + + Assert.assertEquals(2, result.size()); + + List resultTcgaPubVariants = result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + List resultTcgaVariants = result.stream() + .filter(s -> "acc_tcga_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals(new String[] {"EML4-ALK.E6bA20.AB374362", "KIAA1549-BRAF.K16B10.COSF509"}, resultTcgaPubVariants.toArray()); + Assert.assertEquals(0, resultTcgaVariants.size()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesAnyGene1() throws Exception { + + structVarFilterQuery1.getGene1Query() + .setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + structVarFilterQuery2.getGene1Query() + .setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries(molecularProfileIds, + sampleIds, structVarQueries); + + Assert.assertEquals(6, result.size()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesAnyGene2() throws Exception { + + structVarFilterQuery1.getGene2Query() + .setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + structVarFilterQuery2.getGene2Query() + .setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries(molecularProfileIds, + sampleIds, structVarQueries); + + Assert.assertEquals(6, result.size()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesNullGene1() throws Exception { + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries(molecularProfileIds, + sampleIds, Arrays.asList(structVarFilterQueryNullGene1)); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesNullGene2() throws Exception { + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries(molecularProfileIds, + sampleIds, Arrays.asList(structVarFilterQueryNullGene2)); + + Assert.assertEquals(1, result.size()); + } } diff --git a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/StudyMyBatisRepositoryTest.java b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/StudyMyBatisRepositoryTest.java index 47ee9b7bf43..86a194942b3 100644 --- a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/StudyMyBatisRepositoryTest.java +++ b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/StudyMyBatisRepositoryTest.java @@ -222,6 +222,7 @@ public void getTags() throws Exception { Assert.assertEquals("{\"Analyst\": {\"Name\": \"Jack\", \"Email\": \"jack@something.com\"}, \"Load id\": 35}", result.getTags()); } + @Test public void getMultipleTags() throws Exception { List result = studyMyBatisRepository.getTagsForMultipleStudies(Arrays.asList("study_tcga_pub", "acc_tcga")); @@ -229,9 +230,11 @@ public void getMultipleTags() throws Exception { Assert.assertEquals(2, result.size()); CancerStudyTags cancerStudyTags1 = result.get(1); Assert.assertEquals((Integer) 1, cancerStudyTags1.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudyTags1.getStudyId()); Assert.assertEquals("{\"Analyst\": {\"Name\": \"Jack\", \"Email\": \"jack@something.com\"}, \"Load id\": 35}", cancerStudyTags1.getTags()); CancerStudyTags cancerStudyTags2 = result.get(0); Assert.assertEquals((Integer) 2, cancerStudyTags2.getCancerStudyId()); - Assert.assertEquals("{\"Load id\": 36}", cancerStudyTags2.getTags()); + Assert.assertEquals("acc_tcga", cancerStudyTags2.getStudyId()); + Assert.assertEquals("{\"Load id\": 36}", cancerStudyTags2.getTags()); } } diff --git a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/TreatmentMyBatisRepositoryTest.java b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/TreatmentMyBatisRepositoryTest.java index 0ebf28a7405..e61e23cb807 100644 --- a/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/TreatmentMyBatisRepositoryTest.java +++ b/persistence/persistence-mybatis/src/test/java/org/cbioportal/persistence/mybatis/TreatmentMyBatisRepositoryTest.java @@ -134,32 +134,20 @@ public void getShallowSamplesByPatientId() { } @Test - public void getAllUniqueTreatments() { - HashSet expected = new HashSet<>(Collections.singletonList("Madeupanib")); - - Set actual = treatmentRepository.getAllUniqueTreatments( - Collections.singletonList("TCGA-A1-A0SD-01"), - Collections.singletonList("study_tcga_pub"), - ClinicalEventKeyCode.Agent - ); - - Assert.assertEquals(actual, expected); - } + public void hasTreatmentData() { + + Assert.assertEquals(true, treatmentRepository.hasTreatmentData(Collections.singletonList("study_tcga_pub"), ClinicalEventKeyCode.Agent)); + + Assert.assertEquals(false, treatmentRepository.hasTreatmentData(Collections.singletonList("acc_tcga"), ClinicalEventKeyCode.Agent)); - @Test - public void getTreatmentCount() { - Integer expected = 1; - Integer actual = treatmentRepository.getTreatmentCount(Collections.singletonList("study_tcga_pub"), ClinicalEventKeyCode.Agent.getKey()); - - Assert.assertEquals(actual, expected); } @Test - public void getSampleCount() { - Integer expected = 2; - Integer actual = treatmentRepository.getSampleCount(Collections.singletonList("study_tcga_pub")); - - Assert.assertEquals(actual, expected); + public void hasSampleTimelineData() { + + Assert.assertEquals(true, treatmentRepository.hasSampleTimelineData(Collections.singletonList("study_tcga_pub"))); + + Assert.assertEquals(false, treatmentRepository.hasSampleTimelineData(Collections.singletonList("acc_tcga"))); } } \ No newline at end of file diff --git a/persistence/persistence-mybatis/src/test/resources/testContextDatabase.xml b/persistence/persistence-mybatis/src/test/resources/testContextDatabase.xml index 2a8450a5c89..1c9c4183da2 100644 --- a/persistence/persistence-mybatis/src/test/resources/testContextDatabase.xml +++ b/persistence/persistence-mybatis/src/test/resources/testContextDatabase.xml @@ -45,10 +45,20 @@ + + + + mysql + h2 + + + + + diff --git a/persistence/persistence-mybatis/src/test/resources/testSql.sql b/persistence/persistence-mybatis/src/test/resources/testSql.sql index 1963b4b8a3a..f7047bdbdf7 100644 --- a/persistence/persistence-mybatis/src/test/resources/testSql.sql +++ b/persistence/persistence-mybatis/src/test/resources/testSql.sql @@ -125,12 +125,12 @@ INSERT INTO sample (INTERNAL_ID,STABLE_ID,SAMPLE_TYPE,PATIENT_ID) VALUES (18,'TC INSERT INTO sample (INTERNAL_ID,STABLE_ID,SAMPLE_TYPE,PATIENT_ID) VALUES (19,'TCGA-A1-A0SB-01','Primary Solid Tumor',18); -INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,FUNCTIONAL_IMPACT_SCORE,FIS_VALUE,LINK_XVAR,LINK_PDB,LINK_MSA,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,ONCOTATOR_DBSNP_RS,ONCOTATOR_REFSEQ_MRNA_ID,ONCOTATOR_CODON_CHANGE,ONCOTATOR_UNIPROT_ENTRY_NAME,ONCOTATOR_UNIPROT_ACCESSION,ONCOTATOR_PROTEIN_POS_START,ONCOTATOR_PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (2038,672,'17',41244748,41244748,'G','A','Q934*','Nonsense_Mutation','NA',0,'getma.org/?cm=var&var=hg19,17,41244748,G,A&fts=all','NA','NA','37','+','SNP','rs80357223','unknown','rs80357223','NM_007294','c.(2800-2802)CAG>TAG','BRCA1_HUMAN','P38398',934,934,1,'BRCA1 truncating'); -INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,FUNCTIONAL_IMPACT_SCORE,FIS_VALUE,LINK_XVAR,LINK_PDB,LINK_MSA,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,ONCOTATOR_DBSNP_RS,ONCOTATOR_REFSEQ_MRNA_ID,ONCOTATOR_CODON_CHANGE,ONCOTATOR_UNIPROT_ENTRY_NAME,ONCOTATOR_UNIPROT_ACCESSION,ONCOTATOR_PROTEIN_POS_START,ONCOTATOR_PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (22604,672,'17',41258504,41258504,'A','C','C61G','Missense_Mutation','H',4.355,'getma.org/?cm=var&var=hg19,17,41258504,A,C&fts=all','getma.org/pdb.php?prot=BRCA1_HUMAN&from=24&to=64&var=C61G','getma.org/?cm=msa&ty=f&p=BRCA1_HUMAN&rb=24&re=64&var=C61G','37','+','SNP','rs28897672','byCluster','rs28897672','NM_007294','c.(181-183)TGT>GGT','BRCA1_HUMAN','P38398',61,61,1,'BRCA1 C61 missense'); -INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,FUNCTIONAL_IMPACT_SCORE,FIS_VALUE,LINK_XVAR,LINK_PDB,LINK_MSA,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,ONCOTATOR_DBSNP_RS,ONCOTATOR_REFSEQ_MRNA_ID,ONCOTATOR_CODON_CHANGE,ONCOTATOR_UNIPROT_ENTRY_NAME,ONCOTATOR_UNIPROT_ACCESSION,ONCOTATOR_PROTEIN_POS_START,ONCOTATOR_PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (2039,672,'17',41276033,41276033,'C','T','C27_splice','Splice_Site','NA',1.4013e-45,'NA','NA','NA','37','+','SNP','rs80358010','byCluster','rs80358010','NM_007294','c.e2+1','NA','NA',-1,-1,1,'BRCA1 truncating'); -INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,FUNCTIONAL_IMPACT_SCORE,FIS_VALUE,LINK_XVAR,LINK_PDB,LINK_MSA,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,ONCOTATOR_DBSNP_RS,ONCOTATOR_REFSEQ_MRNA_ID,ONCOTATOR_CODON_CHANGE,ONCOTATOR_UNIPROT_ENTRY_NAME,ONCOTATOR_UNIPROT_ACCESSION,ONCOTATOR_PROTEIN_POS_START,ONCOTATOR_PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (2040,207,'17',41244748,41244748,'G','A','Q934*','Nonsense_Mutation','NA',0,'getma.org/?cm=var&var=hg19,17,41244748,G,A&fts=all','NA','NA','37','+','SNP','rs80357223','unknown','rs80357223','NM_007294','c.(2800-2802)CAG>TAG','BRCA1_HUMAN','P38398',934,934,1,'BRCA1 truncating'); -INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,FUNCTIONAL_IMPACT_SCORE,FIS_VALUE,LINK_XVAR,LINK_PDB,LINK_MSA,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,ONCOTATOR_DBSNP_RS,ONCOTATOR_REFSEQ_MRNA_ID,ONCOTATOR_CODON_CHANGE,ONCOTATOR_UNIPROT_ENTRY_NAME,ONCOTATOR_UNIPROT_ACCESSION,ONCOTATOR_PROTEIN_POS_START,ONCOTATOR_PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (2041,207,'17',41258504,41258504,'A','C','C61G','Missense_Mutation','H',4.355,'getma.org/?cm=var&var=hg19,17,41258504,A,C&fts=all','getma.org/pdb.php?prot=BRCA1_HUMAN&from=24&to=64&var=C61G','getma.org/?cm=msa&ty=f&p=BRCA1_HUMAN&rb=24&re=64&var=C61G','37','+','SNP','rs28897672','byCluster','rs28897672','NM_007294','c.(181-183)TGT>GGT','BRCA1_HUMAN','P38398',61,61,1,'BRCA1 C61 missense'); -INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,FUNCTIONAL_IMPACT_SCORE,FIS_VALUE,LINK_XVAR,LINK_PDB,LINK_MSA,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,ONCOTATOR_DBSNP_RS,ONCOTATOR_REFSEQ_MRNA_ID,ONCOTATOR_CODON_CHANGE,ONCOTATOR_UNIPROT_ENTRY_NAME,ONCOTATOR_UNIPROT_ACCESSION,ONCOTATOR_PROTEIN_POS_START,ONCOTATOR_PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (2042,208,'17',41276033,41276033,'C','T','C27_splice','Splice_Site','NA',1.4013e-45,'NA','NA','NA','37','+','SNP','rs80358010','byCluster','rs80358010','NM_007294','c.e2+1','NA','NA',-1,-1,1,'BRCA1 truncating'); +INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,REFSEQ_MRNA_ID,CODON_CHANGE,UNIPROT_ACCESSION,PROTEIN_POS_START,PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (2038,672,'17',41244748,41244748,'G','A','Q934*','Nonsense_Mutation','37','+','SNP','rs80357223','unknown','NM_007294','c.(2800-2802)CAG>TAG','P38398',934,934,1,'BRCA1 truncating'); +INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,REFSEQ_MRNA_ID,CODON_CHANGE,UNIPROT_ACCESSION,PROTEIN_POS_START,PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (22604,672,'17',41258504,41258504,'A','C','C61G','Missense_Mutation','37','+','SNP','rs28897672','byCluster','NM_007294','c.(181-183)TGT>GGT','P38398',61,61,1,'BRCA1 C61 missense'); +INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,REFSEQ_MRNA_ID,CODON_CHANGE,UNIPROT_ACCESSION,PROTEIN_POS_START,PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (2039,672,'17',41276033,41276033,'C','T','C27_splice','Splice_Site','37','+','SNP','rs80358010','byCluster','NM_007294','c.e2+1','NA',-1,-1,1,'BRCA1 truncating'); +INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,REFSEQ_MRNA_ID,CODON_CHANGE,UNIPROT_ACCESSION,PROTEIN_POS_START,PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (2040,207,'17',41244748,41244748,'G','A','Q934*','Nonsense_Mutation','37','+','SNP','rs80357223','unknown','NM_007294','c.(2800-2802)CAG>TAG','P38398',934,934,1,'BRCA1 truncating'); +INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,REFSEQ_MRNA_ID,CODON_CHANGE,UNIPROT_ACCESSION,PROTEIN_POS_START,PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (2041,207,'17',41258504,41258504,'A','C','C61G','Missense_Mutation','37','+','SNP','rs28897672','byCluster','NM_007294','c.(181-183)TGT>GGT','P38398',61,61,1,'BRCA1 C61 missense'); +INSERT INTO mutation_event (MUTATION_EVENT_ID,ENTREZ_GENE_ID,CHR,START_POSITION,END_POSITION,REFERENCE_ALLELE,TUMOR_SEQ_ALLELE,PROTEIN_CHANGE,MUTATION_TYPE,NCBI_BUILD,STRAND,VARIANT_TYPE,DB_SNP_RS,DB_SNP_VAL_STATUS,REFSEQ_MRNA_ID,CODON_CHANGE,UNIPROT_ACCESSION,PROTEIN_POS_START,PROTEIN_POS_END,CANONICAL_TRANSCRIPT,KEYWORD) VALUES (2042,208,'17',41276033,41276033,'C','T','C27_splice','Splice_Site','37','+','SNP','rs80358010','byCluster','NM_007294','c.e2+1','NA',-1,-1,1,'BRCA1 truncating'); INSERT INTO alteration_driver_annotation (ALTERATION_EVENT_ID,GENETIC_PROFILE_ID,SAMPLE_ID, DRIVER_FILTER, DRIVER_FILTER_ANNOTATION, DRIVER_TIERS_FILTER, DRIVER_TIERS_FILTER_ANNOTATION) VALUES (2038,6,6, 'Putative_Driver', 'Pathogenic', 'Tier 1', 'Highly Actionable'); INSERT INTO alteration_driver_annotation (ALTERATION_EVENT_ID,GENETIC_PROFILE_ID,SAMPLE_ID, DRIVER_FILTER, DRIVER_FILTER_ANNOTATION, DRIVER_TIERS_FILTER, DRIVER_TIERS_FILTER_ANNOTATION) VALUES (22604,6,6, 'Putative_Passenger', 'Pathogenic', 'Tier 2', 'Potentially Actionable'); @@ -403,9 +403,9 @@ INSERT INTO structural_variant (GENETIC_PROFILE_ID,SAMPLE_ID,SITE1_ENTREZ_GENE_I INSERT INTO structural_variant (GENETIC_PROFILE_ID,SAMPLE_ID,SITE1_ENTREZ_GENE_ID,SITE1_ENSEMBL_TRANSCRIPT_ID,SITE1_CHROMOSOME,SITE1_REGION,SITE1_REGION_NUMBER,SITE1_CONTIG,SITE1_POSITION,SITE1_DESCRIPTION,SITE2_ENTREZ_GENE_ID,SITE2_ENSEMBL_TRANSCRIPT_ID,SITE2_CHROMOSOME,SITE2_REGION,SITE2_REGION_NUMBER,SITE2_CONTIG,SITE2_POSITION,SITE2_DESCRIPTION,NCBI_BUILD,DNA_SUPPORT,RNA_SUPPORT,TUMOR_READ_COUNT,TUMOR_VARIANT_COUNT,ANNOTATION,EVENT_INFO,COMMENTS,SV_STATUS) VALUES(7,1,8031,'ENST00000344348','10','exon',-1,'q13.4',51582939,'NCOA4-RET.N7R12_1',5979,'ENST00000340058','10','exon',-1,'p13.1',43612031,'NCOA4-RET.N7R12_2','GRCh37','no','yes',100001,80000,'NCOA4-RET.N7R1','Fusion','Gain-of-Function','SOMATIC'); INSERT INTO structural_variant (GENETIC_PROFILE_ID,SAMPLE_ID,SITE1_ENTREZ_GENE_ID,SITE1_ENSEMBL_TRANSCRIPT_ID,SITE1_CHROMOSOME,SITE1_REGION,SITE1_REGION_NUMBER,SITE1_CONTIG,SITE1_POSITION,SITE1_DESCRIPTION,SITE2_ENTREZ_GENE_ID,SITE2_ENSEMBL_TRANSCRIPT_ID,SITE2_CHROMOSOME,SITE2_REGION,SITE2_REGION_NUMBER,SITE2_CONTIG,SITE2_POSITION,SITE2_DESCRIPTION,NCBI_BUILD,DNA_SUPPORT,RNA_SUPPORT,TUMOR_READ_COUNT,TUMOR_VARIANT_COUNT,ANNOTATION,EVENT_INFO,COMMENTS,SV_STATUS) - VALUES(7,1,27436,'ENST00000318522','2','exon',-1,'q13.4',42492091,'EML4-ALK.E6bA20.AB374362_1',238,'ENST00000389048','2','exon',-1,'p13.1',29446394,'EML4-ALK.E6bA20.AB374362_2','GRCh37','no','yes',100002,70000,'EML4-ALK.E6bA20.AB374362','Fusion','Gain-of-Function','GERMLINE'); + VALUES(7,1,27436,'ENST00000318522','2','exon',-1,'q13.4',42492091,'EML4-ALK.E6bA20.AB374362_1',238,'ENST00000389048','2','exon',-1,'p13.1',29446394,'EML4-ALK.E6bA20.AB374362_2','GRCh37','no','yes',100002,70000,'EML4-ALK.E6bA20.AB374362','Fusion','Gain-of-Function','GERMLINE'); INSERT INTO structural_variant (GENETIC_PROFILE_ID,SAMPLE_ID,SITE1_ENTREZ_GENE_ID,SITE1_ENSEMBL_TRANSCRIPT_ID,SITE1_CHROMOSOME,SITE1_REGION,SITE1_REGION_NUMBER,SITE1_CONTIG,SITE1_POSITION,SITE1_DESCRIPTION,SITE2_ENTREZ_GENE_ID,SITE2_ENSEMBL_TRANSCRIPT_ID,SITE2_CHROMOSOME,SITE2_REGION,SITE2_REGION_NUMBER,SITE2_CONTIG,SITE2_POSITION,SITE2_DESCRIPTION,NCBI_BUILD,DNA_SUPPORT,RNA_SUPPORT,TUMOR_READ_COUNT,TUMOR_VARIANT_COUNT,ANNOTATION,EVENT_INFO,COMMENTS,SV_STATUS) - VALUES(7,2,27436,'ENST00000318522','2','exon',-1,'q13.4',42492091,'EML4-ALK.E6bA20.AB374362_1',238,'ENST00000389048','2','exon',-1,'p13.1',29446394,'EML4-ALK.E6bA20.AB374362_2','GRCh37','no','yes',100002,70000,'EML4-ALK.E6bA20.AB374362','Fusion','Gain-of-Function','SOMATIC'); + VALUES(7,2,27436,'ENST00000318522','2','exon',-1,'q13.4',42492091,'EML4-ALK.E6bA20.AB374362_1',238,'ENST00000389048','2','exon',-1,'p13.1',29446394,'EML4-ALK.E6bA20.AB374362_2','GRCh37','no','yes',100002,70000,'EML4-ALK.E6bA20.AB374362-2','Fusion','Gain-of-Function','SOMATIC'); INSERT INTO structural_variant (GENETIC_PROFILE_ID,SAMPLE_ID,SITE1_ENTREZ_GENE_ID,SITE1_ENSEMBL_TRANSCRIPT_ID,SITE1_CHROMOSOME,SITE1_REGION,SITE1_REGION_NUMBER,SITE1_CONTIG,SITE1_POSITION,SITE1_DESCRIPTION,SITE2_ENTREZ_GENE_ID,SITE2_ENSEMBL_TRANSCRIPT_ID,SITE2_CHROMOSOME,SITE2_REGION,SITE2_REGION_NUMBER,SITE2_CONTIG,SITE2_POSITION,SITE2_DESCRIPTION,NCBI_BUILD,DNA_SUPPORT,RNA_SUPPORT,TUMOR_READ_COUNT,TUMOR_VARIANT_COUNT,ANNOTATION,EVENT_INFO,COMMENTS,SV_STATUS) VALUES(7,1,7113,'ENST00000332149','21','exon',-1,'q13.4',42880007,'TMPRSS2-ERG.T1E2.COSF23.1_1',2078,'ENST00000442448','21','exon',-1,'p13.1',39956869,'TMPRSS2-ERG.T1E2.COSF23.1_2','GRCh37','no','yes',100003,60000,'TMPRSS2-ERG.T1E2.COSF23.1','Fusion','Gain-of-Function','SOMATIC'); INSERT INTO structural_variant (GENETIC_PROFILE_ID,SAMPLE_ID,SITE1_ENTREZ_GENE_ID,SITE1_ENSEMBL_TRANSCRIPT_ID,SITE1_CHROMOSOME,SITE1_REGION,SITE1_REGION_NUMBER,SITE1_CONTIG,SITE1_POSITION,SITE1_DESCRIPTION,SITE2_ENTREZ_GENE_ID,SITE2_ENSEMBL_TRANSCRIPT_ID,SITE2_CHROMOSOME,SITE2_REGION,SITE2_REGION_NUMBER,SITE2_CONTIG,SITE2_POSITION,SITE2_DESCRIPTION,NCBI_BUILD,DNA_SUPPORT,RNA_SUPPORT,TUMOR_READ_COUNT,TUMOR_VARIANT_COUNT,ANNOTATION,EVENT_INFO,COMMENTS,SV_STATUS) @@ -413,13 +413,19 @@ INSERT INTO structural_variant (GENETIC_PROFILE_ID,SAMPLE_ID,SITE1_ENTREZ_GENE_I INSERT INTO structural_variant (GENETIC_PROFILE_ID,SAMPLE_ID,SITE1_ENTREZ_GENE_ID,SITE1_ENSEMBL_TRANSCRIPT_ID,SITE1_CHROMOSOME,SITE1_REGION,SITE1_REGION_NUMBER,SITE1_CONTIG,SITE1_POSITION,SITE1_DESCRIPTION,SITE2_ENTREZ_GENE_ID,SITE2_ENSEMBL_TRANSCRIPT_ID,SITE2_CHROMOSOME,SITE2_REGION,SITE2_REGION_NUMBER,SITE2_CONTIG,SITE2_POSITION,SITE2_DESCRIPTION,NCBI_BUILD,DNA_SUPPORT,RNA_SUPPORT,TUMOR_READ_COUNT,TUMOR_VARIANT_COUNT,ANNOTATION,EVENT_INFO,COMMENTS,SV_STATUS) VALUES(13,15,57670,'ENST00000242365','7','exon',-1,'q13.4',138536968,'KIAA1549-BRAF.K16B10.COSF509_1',673,'ENST00000288602','7','exon',-1,'p13.1',140482957,'KIAA1549-BRAF.K16B10.COSF509_2','GRCh37','no','yes',100000,90000,'KIAA1549-BRAF.K16B10.COSF509','Fusion','Gain-of-Function','SOMATIC'); INSERT INTO structural_variant (GENETIC_PROFILE_ID,SAMPLE_ID,SITE1_ENTREZ_GENE_ID,SITE1_ENSEMBL_TRANSCRIPT_ID,SITE1_CHROMOSOME,SITE1_REGION,SITE1_REGION_NUMBER,SITE1_CONTIG,SITE1_POSITION,SITE1_DESCRIPTION,SITE2_ENTREZ_GENE_ID,SITE2_ENSEMBL_TRANSCRIPT_ID,SITE2_CHROMOSOME,SITE2_REGION,SITE2_REGION_NUMBER,SITE2_CONTIG,SITE2_POSITION,SITE2_DESCRIPTION,NCBI_BUILD,DNA_SUPPORT,RNA_SUPPORT,TUMOR_READ_COUNT,TUMOR_VARIANT_COUNT,ANNOTATION,EVENT_INFO,COMMENTS,SV_STATUS) - VALUES(13,15,8031,'ENST00000344348','10','exon',-1,'q13.4',51582939,'NCOA4-RET.N7R12_1',5979,'ENST00000340058','10','exon',-1,'p13.1',43612031,'NCOA4-RET.N7R12_2','GRCh37','no','yes',100001,80000,'NCOA4-RET.N7R1','Fusion','Gain-of-Function','SOMATIC'); + VALUES(13,15,8031,'ENST00000344348','10','exon',-1,'q13.4',51582939,'NCOA4-RET.N7R12_1',5979,'ENST00000340058','10','exon',-1,'p13.1',43612031,'NCOA4-RET.N7R12_2','GRCh37','no','yes',100001,80000,'NCOA4-RET.N7R1-2','Fusion','Gain-of-Function','SOMATIC'); INSERT INTO structural_variant (GENETIC_PROFILE_ID,SAMPLE_ID,SITE1_ENTREZ_GENE_ID,SITE1_ENSEMBL_TRANSCRIPT_ID,SITE1_CHROMOSOME,SITE1_REGION,SITE1_REGION_NUMBER,SITE1_CONTIG,SITE1_POSITION,SITE1_DESCRIPTION,SITE2_ENTREZ_GENE_ID,SITE2_ENSEMBL_TRANSCRIPT_ID,SITE2_CHROMOSOME,SITE2_REGION,SITE2_REGION_NUMBER,SITE2_CONTIG,SITE2_POSITION,SITE2_DESCRIPTION,NCBI_BUILD,DNA_SUPPORT,RNA_SUPPORT,TUMOR_READ_COUNT,TUMOR_VARIANT_COUNT,ANNOTATION,EVENT_INFO,COMMENTS,SV_STATUS) VALUES(13,15,7113,'ENST00000332149','21','exon',-1,'q13.4',42880007,'TMPRSS2-ERG.T1E2.COSF23.1_1',2078,'ENST00000442448','21','exon',-1,'p13.1',39956869,'TMPRSS2-ERG.T1E2.COSF23.1_2','GRCh37','no','yes',100003,60000,'TMPRSS2-ERG.T1E2.COSF23.1','Fusion','Gain-of-Function','Germline'); INSERT INTO structural_variant (GENETIC_PROFILE_ID,SAMPLE_ID,SITE1_ENTREZ_GENE_ID,SITE1_ENSEMBL_TRANSCRIPT_ID,SITE1_CHROMOSOME,SITE1_REGION,SITE1_REGION_NUMBER,SITE1_CONTIG,SITE1_POSITION,SITE1_DESCRIPTION,SITE2_ENTREZ_GENE_ID,SITE2_ENSEMBL_TRANSCRIPT_ID,SITE2_CHROMOSOME,SITE2_REGION,SITE2_REGION_NUMBER,SITE2_CONTIG,SITE2_POSITION,SITE2_DESCRIPTION,NCBI_BUILD,DNA_SUPPORT,RNA_SUPPORT,TUMOR_READ_COUNT,TUMOR_VARIANT_COUNT,ANNOTATION,EVENT_INFO,COMMENTS,SV_STATUS) VALUES(13,15,8031,'ENST00000344348','10','exon',-1,'q13.4',51582939,'NCOA4-NULL',NULL,'ENST00000340058_NULL','10','exon',-1,'p13.1',43612031,'NCOA4-NULL','GRCh37','no','yes',100001,80000,'NCOA4-NULL','Fusion','Gain-of-Function','SOMATIC'); -INSERT INTO alteration_driver_annotation (ALTERATION_EVENT_ID,GENETIC_PROFILE_ID,SAMPLE_ID, DRIVER_FILTER, DRIVER_FILTER_ANNOTATION, DRIVER_TIERS_FILTER, DRIVER_TIERS_FILTER_ANNOTATION) VALUES (1,7,1, 'Putative_Passenger', 'Pathogenic', 'Tier 1', 'Potentially Actionable'); +INSERT INTO alteration_driver_annotation (ALTERATION_EVENT_ID,GENETIC_PROFILE_ID,SAMPLE_ID, DRIVER_FILTER, DRIVER_FILTER_ANNOTATION, DRIVER_TIERS_FILTER, DRIVER_TIERS_FILTER_ANNOTATION) + VALUES (1,7,1, 'Putative_Passenger', 'Pathogenic', 'Tier 1', 'Potentially Actionable'); + +INSERT INTO alteration_driver_annotation (ALTERATION_EVENT_ID,GENETIC_PROFILE_ID,SAMPLE_ID, DRIVER_FILTER, DRIVER_FILTER_ANNOTATION, DRIVER_TIERS_FILTER, DRIVER_TIERS_FILTER_ANNOTATION) + VALUES (3,7,1, 'Putative_Driver', 'Pathogenic', 'Class 2', 'Highly Actionable'); +INSERT INTO alteration_driver_annotation (ALTERATION_EVENT_ID,GENETIC_PROFILE_ID,SAMPLE_ID, DRIVER_FILTER, DRIVER_FILTER_ANNOTATION, DRIVER_TIERS_FILTER, DRIVER_TIERS_FILTER_ANNOTATION) + VALUES (5,7,2, 'Putative_Driver', 'Pathogenic', 'Class 3', 'Highly Actionable'); INSERT INTO mut_sig (CANCER_STUDY_ID,ENTREZ_GENE_ID,RANK,NumBasesCovered,NumMutations,P_VALUE,Q_VALUE) VALUES (1,207,1,998421,17,0.00000315,0.00233); INSERT INTO mut_sig (CANCER_STUDY_ID,ENTREZ_GENE_ID,RANK,NumBasesCovered,NumMutations,P_VALUE,Q_VALUE) VALUES (1,208,2,3200341,351,0.000000012,0.00000000000212); diff --git a/pom.xml b/pom.xml index aa36c2ebcb7..c6068832cdd 100644 --- a/pom.xml +++ b/pom.xml @@ -276,7 +276,7 @@ - v5.2.9 + v5.4.1 com.github.cbioportal 5.2.20.RELEASE 5.3.0.RELEASE @@ -305,7 +305,7 @@ com.mysql.jdbc.Driver - jdbc:mysql://127.0.0.1:3306/cgds_test?sessionVariables=default_storage_engine=InnoDB&allowLoadLocalInfile=true + jdbc:mysql://127.0.0.1:3306/cgds_test?useSSL=false&sessionVariables=default_storage_engine=InnoDB&allowLoadLocalInfile=true&allowPublicKeyRetrieval=true cbio_user somepassword @@ -314,7 +314,7 @@ 720 - 2.12.16 + 2.13.1 diff --git a/portal/pom.xml b/portal/pom.xml index 0cf3cf219fe..863d73a87d9 100644 --- a/portal/pom.xml +++ b/portal/pom.xml @@ -215,8 +215,6 @@ ${db.test.username} ${db.test.password} - 127.0.0.1:3306 - cgds_test ${db.test.url} diff --git a/portal/src/integration-tests/saml-oauth2-setup/pom.xml b/portal/src/integration-tests/saml-oauth2-setup/pom.xml index ef5f053e0ee..2db22342264 100644 --- a/portal/src/integration-tests/saml-oauth2-setup/pom.xml +++ b/portal/src/integration-tests/saml-oauth2-setup/pom.xml @@ -66,8 +66,6 @@ ${env.CBIO_TEST_DB_USR} ${env.CBIO_TEST_DB_PSW} - ${env.CBIO_TEST_DB_HOST} - ${env.CBIO_TEST_DB_NAME} ${env.CBIO_TEST_DB_CONNECTION_STRING} file://${project.basedir}/testSamlKeystore.jks diff --git a/portal/src/main/webapp/WEB-INF/jsp/global/frontend_config.jsp b/portal/src/main/webapp/WEB-INF/jsp/global/frontend_config.jsp index d1a118ff7f1..0d20e91ebde 100644 --- a/portal/src/main/webapp/WEB-INF/jsp/global/frontend_config.jsp +++ b/portal/src/main/webapp/WEB-INF/jsp/global/frontend_config.jsp @@ -30,6 +30,7 @@ window.legacySupportFrontendConfig = { skinRightNavShowExamples : <%=GlobalProperties.showRightNavExamples()%>, skinRightNavShowTestimonials : <%=GlobalProperties.showRightNavTestimonials()%>, skinRightNavShowWhatsNew : <%=GlobalProperties.showRightNavWhatsNew()%>, + skinRightNavShowWebTours: <%=GlobalProperties.showRightNavInteractiveTour()%>, skinRightNavExamplesHTML : '<%=GlobalProperties.getExamplesRightColumnHtml()%>', skinRightNavExamplesHTML : '<%=GlobalProperties.getExamplesRightColumnHtml()%>', skinRightNavWhatsNewBlurb : '<%=GlobalProperties.getRightNavWhatsNewBlurb()%>', diff --git a/portal/src/main/webapp/config_service.jsp b/portal/src/main/webapp/config_service.jsp index 631c5027b8d..495bce3e1f5 100644 --- a/portal/src/main/webapp/config_service.jsp +++ b/portal/src/main/webapp/config_service.jsp @@ -31,13 +31,13 @@ String[] propNameArray = { "app.version", "app.name", - "dat.method", "oncoprint.custom_driver_annotation.binary.menu_label", "disabled_tabs", "civic.url", "oncoprint.custom_driver_annotation.binary.default", "oncoprint.oncokb.default", "oncoprint.hotspots.default", + "oncoprint.clustered.default", "genomenexus.url", "genomenexus.url.grch38", "google_analytics_profile_id", @@ -98,6 +98,7 @@ "skin.right_nav.show_whats_new", "skin.right_nav.show_twitter", "skin.right_nav.whats_new_blurb", + "skin.right_nav.show_web_tours", "skin.show_about_tab", "skin.show_data_tab", "skin.show_faqs_tab", @@ -113,6 +114,7 @@ "skin.home_page.unauthorized_studies_global_message", "skin.show_settings_menu", "skin.hide_logout_button", + "enable_cross_study_expression", "quick_search.enabled", "default_cross_cancer_study_session_id", "default_cross_cancer_study_list", @@ -131,6 +133,7 @@ "enable_request_body_gzip_compression", "enable_treatment_groups", "query_product_limit", + "studyview.max_samples_selected", "clinical_attribute_product_limit", "saml.logout.local", "skin.citation_rule_text", @@ -144,7 +147,10 @@ "skin.patient_view.copy_number_table.columns.show_on_init", "skin.patient_view.structural_variant_table.columns.show_on_init", "comparison.categorical_na_values", - "skin.hide_download_controls" + "study_download_url", + "skin.home_page.show_reference_genome", + "vaf.sequential_mode.default", + "vaf.log_scale.default" }; @@ -179,6 +185,8 @@ obj.put("oncoprint_clinical_tracks_config_json",GlobalProperties.getOncoprintClinicalTracksConfigJson()); + obj.put("skin_patient_view_custom_sample_type_colors_json", GlobalProperties.getSkinPatientViewCustomSampleTypeColorsJson()); + obj.put("authenticationMethod",GlobalProperties.authenticationMethod()); obj.put("mskWholeSlideViewerToken", GlobalProperties.getMskWholeSlideViewerToken()); @@ -200,6 +208,10 @@ obj.put("sessionServiceEnabled", !StringUtils.isEmpty(GlobalProperties.getSessionServiceUrl())); + obj.put("skin_hide_download_controls", GlobalProperties.getDownloadControl()); + + obj.put("dat_method", GlobalProperties.getDataAccessTokenMethod()); + out.println(obj.toJSONString()); diff --git a/portal/src/org/mskcc/portal/model/MafRecord.java b/portal/src/org/mskcc/portal/model/MafRecord.java index ceaab613ce5..78cef29dfd6 100644 --- a/portal/src/org/mskcc/portal/model/MafRecord.java +++ b/portal/src/org/mskcc/portal/model/MafRecord.java @@ -47,10 +47,10 @@ public class MafRecord { private int normalAltCount; private int normalRefCount; - private String oncotatorProteinChange; - private String oncotatorVariantClassification; - private String oncotatorCosmicOverlapping; - private String oncotatorDbSnpRs; + private String mafProteinChange; + private String mafVariantClassification; + private String mafCosmicOverlapping; + private String mafDbSnpRs; public String getChr() { return chr; @@ -340,37 +340,37 @@ public void setNormalRefCount(int normalRefCount) { this.normalRefCount = normalRefCount; } - public String getOncotatorProteinChange() { - return oncotatorProteinChange; + public String getMafProteinChange() { + return mafProteinChange; } - public void setOncotatorProteinChange(String oncotatorProteinChange) { - this.oncotatorProteinChange = oncotatorProteinChange; + public void setMafProteinChange(String mafProteinChange) { + this.mafProteinChange = mafProteinChange; } - public String getOncotatorVariantClassification() { - return oncotatorVariantClassification; + public String getMafVariantClassification() { + return mafVariantClassification; } - public void setOncotatorVariantClassification( - String oncotatorVariantClassification) { - this.oncotatorVariantClassification = oncotatorVariantClassification; + public void setMafVariantClassification( + String mafVariantClassification) { + this.mafVariantClassification = mafVariantClassification; } - public String getOncotatorCosmicOverlapping() { - return oncotatorCosmicOverlapping; + public String getMafCosmicOverlapping() { + return mafCosmicOverlapping; } - public void setOncotatorCosmicOverlapping(String oncotatorCosmicOverlapping) { - this.oncotatorCosmicOverlapping = oncotatorCosmicOverlapping; + public void setMafCosmicOverlapping(String mafCosmicOverlapping) { + this.mafCosmicOverlapping = mafCosmicOverlapping; } - public String getOncotatorDbSnpRs() { - return oncotatorDbSnpRs; + public String getMafDbSnpRs() { + return mafDbSnpRs; } - public void setOncotatorDbSnpRs(String oncotatorDbSnpRs) { - this.oncotatorDbSnpRs = oncotatorDbSnpRs; + public void setMafDbSnpRs(String mafDbSnpRs) { + this.mafDbSnpRs = mafDbSnpRs; } diff --git a/requirements.txt b/requirements.txt index 42ee5391458..5cd1f3ba8b7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ requests==2.20.0 markupsafe==2.0.1 Jinja2==2.11.3 mysqlclient==2.1.0 -PyYAML==5.4 +PyYAML==6.0.1 +dsnparse==0.1.15 diff --git a/retype.yml b/retype.yml index 4e3c71a5799..146442fdf6a 100644 --- a/retype.yml +++ b/retype.yml @@ -1,5 +1,6 @@ input: ./docs output: .retype +url: https://docs.cbioportal.org branding: title: cBioPortal Docs logo: images/cbio-logo.png diff --git a/service/pom.xml b/service/pom.xml index 65c11c55a27..a46d74484dc 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -24,6 +24,29 @@ org.mskcc.cbio permission-evaluator + + com.github.cbioportal + session-service + model + + + org.apache.logging.log4j + log4j-to-slf4j + + + ch.qos.logback + logback-classic + + + spring-boot-starter-web + org.springframework.boot + + + spring-boot-starter-data-mongodb + org.springframework.boot + + + org.springframework spring-test @@ -57,6 +80,10 @@ org.apache.commons commons-collections4 + + commons-codec + commons-codec + org.mockito mockito-core diff --git a/service/src/main/java/org/cbioportal/service/AlterationCountService.java b/service/src/main/java/org/cbioportal/service/AlterationCountService.java index 9145653d2f7..5966f725a8d 100644 --- a/service/src/main/java/org/cbioportal/service/AlterationCountService.java +++ b/service/src/main/java/org/cbioportal/service/AlterationCountService.java @@ -8,41 +8,46 @@ public interface AlterationCountService { - Pair, Long> getSampleAlterationCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); + Pair, Long> getSampleAlterationGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); - Pair, Long> getPatientAlterationCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); + Pair, Long> getPatientAlterationGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); - Pair, Long> getSampleMutationCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); + Pair, Long> getSampleMutationGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); - Pair, Long> getPatientMutationCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); + Pair, Long> getPatientMutationGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); - Pair, Long> getSampleStructuralVariantCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); + Pair, Long> getSampleStructuralVariantGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); - Pair, Long> getPatientStructuralVariantCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); + Pair, Long> getPatientStructuralVariantGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); + + Pair, Long> getSampleStructuralVariantCounts(List molecularProfileCaseIdentifiers, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); // Should be restored when old CNA count endpoint is retired // Pair, Long> getSampleCnaCounts(List molecularProfileCaseIdentifiers, @@ -58,16 +63,16 @@ Pair, Long> getPatientStructuralVariantCounts(List, Long> getSampleCnaCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); + Pair, Long> getSampleCnaGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); - Pair, Long> getPatientCnaCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); + Pair, Long> getPatientCnaGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); } diff --git a/service/src/main/java/org/cbioportal/service/AttributeByStudyService.java b/service/src/main/java/org/cbioportal/service/AttributeByStudyService.java new file mode 100644 index 00000000000..a1f198d1e15 --- /dev/null +++ b/service/src/main/java/org/cbioportal/service/AttributeByStudyService.java @@ -0,0 +1,9 @@ +package org.cbioportal.service; + +import org.cbioportal.model.ClinicalAttribute; + +import java.util.List; + +public interface AttributeByStudyService { + List getClinicalAttributesByStudyIdsAndAttributeIds(List studyIds, List attributeIds); +} diff --git a/service/src/main/java/org/cbioportal/service/ClinicalAttributeService.java b/service/src/main/java/org/cbioportal/service/ClinicalAttributeService.java index 4babd2f6f82..3b648824419 100644 --- a/service/src/main/java/org/cbioportal/service/ClinicalAttributeService.java +++ b/service/src/main/java/org/cbioportal/service/ClinicalAttributeService.java @@ -8,7 +8,7 @@ import java.util.List; -public interface ClinicalAttributeService { +public interface ClinicalAttributeService extends AttributeByStudyService { List getAllClinicalAttributes(String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); @@ -31,5 +31,4 @@ List getAllClinicalAttributesInStudy(String studyId, String p List getClinicalAttributeCountsBySampleListId(String sampleListId); - List getClinicalAttributesByStudyIdsAndAttributeIds(List studyIds, List attributeIds); } diff --git a/service/src/main/java/org/cbioportal/service/ClinicalDataService.java b/service/src/main/java/org/cbioportal/service/ClinicalDataService.java index 3ba05c8f784..972913ce2e4 100644 --- a/service/src/main/java/org/cbioportal/service/ClinicalDataService.java +++ b/service/src/main/java/org/cbioportal/service/ClinicalDataService.java @@ -52,6 +52,9 @@ BaseMeta fetchMetaClinicalData(List studyIds, List ids, List getPatientClinicalDataDetailedToSample(List studyIds, List patientIds, List attributeIds); - List fetchSampleClinicalDataClinicalTable(List studyIds, List sampleIds, Integer pageSize, - Integer pageNumber, String searchTerm, String sortBy, String direction); + List fetchSampleClinicalTable(List studyIds, List sampleIds, Integer pageSize, + Integer pageNumber, String searchTerm, String sortBy, String direction); + + Integer fetchSampleClinicalTableCount(List studyIds, List sampleIds, String searchTerm, + String sortBy, String direction); } diff --git a/service/src/main/java/org/cbioportal/service/CustomDataService.java b/service/src/main/java/org/cbioportal/service/CustomDataService.java new file mode 100644 index 00000000000..6f1b96f8c65 --- /dev/null +++ b/service/src/main/java/org/cbioportal/service/CustomDataService.java @@ -0,0 +1,10 @@ +package org.cbioportal.service; + +import org.cbioportal.service.util.CustomDataSession; + +import java.util.List; +import java.util.Map; + +public interface CustomDataService { + Map getCustomDataSessions(List attributes); +} diff --git a/service/src/main/java/org/cbioportal/service/ExpressionEnrichmentService.java b/service/src/main/java/org/cbioportal/service/ExpressionEnrichmentService.java index ae602d46b35..d3c2a444bd8 100644 --- a/service/src/main/java/org/cbioportal/service/ExpressionEnrichmentService.java +++ b/service/src/main/java/org/cbioportal/service/ExpressionEnrichmentService.java @@ -7,6 +7,8 @@ import org.cbioportal.model.GenericAssayEnrichment; import org.cbioportal.model.GenomicEnrichment; import org.cbioportal.model.MolecularProfileCaseIdentifier; +import org.cbioportal.model.GenericAssayBinaryEnrichment; +import org.cbioportal.model.GenericAssayCategoricalEnrichment; import org.cbioportal.service.exception.MolecularProfileNotFoundException; public interface ExpressionEnrichmentService { @@ -15,8 +17,18 @@ List getGenomicEnrichments(String molecularProfileId, Map> molecularProfileCaseSets, EnrichmentType enrichmentType) throws MolecularProfileNotFoundException; - List getGenericAssayEnrichments(String molecularProfileId, + List getGenericAssayNumericalEnrichments(String molecularProfileId, Map> molecularProfileCaseSets, EnrichmentType enrichmentType) throws MolecularProfileNotFoundException; + List getGenericAssayBinaryEnrichments( + String molecularProfileId, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException; + + List getGenericAssayCategoricalEnrichments(String molecularProfileId, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException; } diff --git a/service/src/main/java/org/cbioportal/service/StructuralVariantService.java b/service/src/main/java/org/cbioportal/service/StructuralVariantService.java index 4eafa15bbdc..6fe7dc5d34d 100644 --- a/service/src/main/java/org/cbioportal/service/StructuralVariantService.java +++ b/service/src/main/java/org/cbioportal/service/StructuralVariantService.java @@ -26,6 +26,7 @@ import java.util.List; import org.cbioportal.model.GeneFilterQuery; +import org.cbioportal.model.StructuralVariantFilterQuery; import org.cbioportal.model.StructuralVariant; import org.cbioportal.model.StructuralVariantQuery; @@ -42,4 +43,7 @@ List fetchStructuralVariantsByGeneQueries(List molecu List sampleIds, List geneQueries); + List fetchStructuralVariantsByStructVarQueries(List molecularProfileIds, + List sampleIds, + List structVarQueries); } \ No newline at end of file diff --git a/service/src/main/java/org/cbioportal/service/StudyViewService.java b/service/src/main/java/org/cbioportal/service/StudyViewService.java index b9850d73df7..67191ea7588 100644 --- a/service/src/main/java/org/cbioportal/service/StudyViewService.java +++ b/service/src/main/java/org/cbioportal/service/StudyViewService.java @@ -1,9 +1,9 @@ package org.cbioportal.service; +import org.apache.commons.math3.util.Pair; import org.cbioportal.model.*; import org.cbioportal.service.exception.MolecularProfileNotFoundException; import org.cbioportal.service.exception.StudyNotFoundException; -import org.springframework.cache.annotation.Cacheable; import java.util.List; @@ -15,9 +15,14 @@ List getMutationAlterationCountByGenes(List study List getStructuralVariantAlterationCountByGenes(List studyIds, List sampleIds, AlterationFilter annotationFilter) throws StudyNotFoundException; + + List getStructuralVariantAlterationCounts(List studyIds, List sampleIds, AlterationFilter annotationFilters); List getCNAAlterationCountByGenes(List studyIds, List sampleIds, AlterationFilter annotationFilter) throws StudyNotFoundException; + List getCNAAlterationCountsByGeneSpecific(List studyIds, List sampleIds, List> genomicDataFilters); + List fetchGenericAssayDataCounts(List sampleIds, List studyIds, List stableIds, List profileTypes); + } diff --git a/service/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java b/service/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java index 0c08a4f1bbb..0e5484abf2d 100644 --- a/service/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java +++ b/service/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java @@ -8,7 +8,6 @@ import org.cbioportal.persistence.MolecularProfileRepository; import org.cbioportal.service.AlterationCountService; import org.cbioportal.service.util.AlterationEnrichmentUtil; -import org.cbioportal.service.util.MolecularProfileUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -28,63 +27,59 @@ public class AlterationCountServiceImpl implements AlterationCountService { @Autowired private AlterationEnrichmentUtil alterationEnrichmentUtilCna; @Autowired - private MolecularProfileUtil molecularProfileUtil; + private AlterationEnrichmentUtil alterationEnrichmentUtilStructVar; @Autowired private MolecularProfileRepository molecularProfileRepository; @Override - public Pair, Long> getSampleAlterationCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { + public Pair, Long> getSampleAlterationGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { Function, List> dataFetcher = profileCaseIdentifiers -> - alterationRepository.getSampleAlterationCounts(new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); + alterationRepository.getSampleAlterationGeneCounts(new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); BiFunction, List, Long> includeFrequencyFunction = (a, b) -> alterationEnrichmentUtil.includeFrequencyForSamples(a, b, includeMissingAlterationsFromGenePanel); - Function keyGenerator = d -> d.getEntrezGeneId().toString(); - - return getAlterationCounts( + return getAlterationGeneCounts( molecularProfileCaseIdentifiers, includeFrequency, dataFetcher, - includeFrequencyFunction, - keyGenerator); + includeFrequencyFunction + ); } @Override - public Pair, Long> getPatientAlterationCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { + public Pair, Long> getPatientAlterationGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { Function, List> dataFetcher = profileCaseIdentifiers -> - alterationRepository.getPatientAlterationCounts(profileCaseIdentifiers, entrezGeneIds, alterationFilter); + alterationRepository.getPatientAlterationGeneCounts(new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); BiFunction, List, Long> includeFrequencyFunction = (a, b) -> alterationEnrichmentUtil.includeFrequencyForPatients(a, b, includeMissingAlterationsFromGenePanel); - Function keyGenerator = d -> d.getEntrezGeneId().toString(); - - return getAlterationCounts( + return getAlterationGeneCounts( molecularProfileCaseIdentifiers, includeFrequency, dataFetcher, - includeFrequencyFunction, - keyGenerator); + includeFrequencyFunction + ); } @Override - public Pair, Long> getSampleMutationCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - return getSampleAlterationCounts(molecularProfileCaseIdentifiers, + public Pair, Long> getSampleMutationGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + return getSampleAlterationGeneCounts(molecularProfileCaseIdentifiers, entrezGeneIds, includeFrequency, includeMissingAlterationsFromGenePanel, @@ -93,12 +88,12 @@ public Pair, Long> getSampleMutationCounts(List, Long> getPatientMutationCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - return getPatientAlterationCounts(molecularProfileCaseIdentifiers, + public Pair, Long> getPatientMutationGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + return getPatientAlterationGeneCounts(molecularProfileCaseIdentifiers, entrezGeneIds, includeFrequency, includeMissingAlterationsFromGenePanel, @@ -106,12 +101,12 @@ public Pair, Long> getPatientMutationCounts(List, Long> getSampleStructuralVariantCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - return getSampleAlterationCounts(molecularProfileCaseIdentifiers, + public Pair, Long> getSampleStructuralVariantGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + return getSampleAlterationGeneCounts(molecularProfileCaseIdentifiers, entrezGeneIds, includeFrequency, includeMissingAlterationsFromGenePanel, @@ -120,12 +115,12 @@ public Pair, Long> getSampleStructuralVariantCounts( } @Override - public Pair, Long> getPatientStructuralVariantCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - return getPatientAlterationCounts(molecularProfileCaseIdentifiers, + public Pair, Long> getPatientStructuralVariantGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + return getPatientAlterationGeneCounts(molecularProfileCaseIdentifiers, entrezGeneIds, includeFrequency, includeMissingAlterationsFromGenePanel, @@ -133,6 +128,26 @@ public Pair, Long> getPatientStructuralVariantCounts ); } + @Override + public Pair, Long> getSampleStructuralVariantCounts(List molecularProfileCaseIdentifiers, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + + Function, List> dataFetcher = profileCaseIdentifiers -> + alterationRepository.getSampleStructuralVariantCounts(new TreeSet<>(profileCaseIdentifiers), alterationFilter); + + BiFunction, List, Long> includeFrequencyFunction = + (a, b) -> alterationEnrichmentUtilStructVar.includeFrequencyForSamples(a, b, includeMissingAlterationsFromGenePanel); + + return getAlterationGeneCounts( + molecularProfileCaseIdentifiers, + includeFrequency, + dataFetcher, + includeFrequencyFunction + ); + } + // -- Should be reinstated when the legacy CNA count endpoint retires // @Override // public List getSampleCnaCounts(List molecularProfileCaseIdentifiers, @@ -163,57 +178,56 @@ public Pair, Long> getPatientStructuralVariantCounts // } @Override - public Pair, Long> getSampleCnaCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { + public Pair, Long> getSampleCnaGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { Function, List> dataFetcher = profileCaseIdentifiers -> - alterationRepository.getSampleCnaCounts(new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); + alterationRepository.getSampleCnaGeneCounts(new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); BiFunction, List, Long> includeFrequencyFunction = (a, b) -> alterationEnrichmentUtilCna.includeFrequencyForSamples(a, b, includeMissingAlterationsFromGenePanel); Function keyGenerator = d -> d.getEntrezGeneId().toString() + d.getAlteration().toString(); - return getAlterationCounts( + return getAlterationGeneCounts( molecularProfileCaseIdentifiers, includeFrequency, dataFetcher, - includeFrequencyFunction, - keyGenerator); + includeFrequencyFunction + ); } @Override - public Pair, Long> getPatientCnaCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { + public Pair, Long> getPatientCnaGeneCounts(List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { Function, List> dataFetcher = profileCaseIdentifiers -> - alterationRepository.getPatientCnaCounts(profileCaseIdentifiers, entrezGeneIds, alterationFilter); + alterationRepository.getPatientCnaGeneCounts(new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); BiFunction, List, Long> includeFrequencyFunction = (a, b) -> alterationEnrichmentUtilCna.includeFrequencyForPatients(a, b, includeMissingAlterationsFromGenePanel); Function keyGenerator = d -> d.getEntrezGeneId().toString() + d.getAlteration().toString(); - return getAlterationCounts( + return getAlterationGeneCounts( molecularProfileCaseIdentifiers, includeFrequency, dataFetcher, - includeFrequencyFunction, - keyGenerator); + includeFrequencyFunction + ); } - private Pair, Long> getAlterationCounts( + private Pair, Long> getAlterationGeneCounts( List molecularProfileCaseIdentifiers, boolean includeFrequency, Function, List> dataFetcher, - BiFunction, List, Long> includeFrequencyFunction, - Function keyGenerator) { + BiFunction, List, Long> includeFrequencyFunction) { List alterationCountByGenes; AtomicReference profiledCasesCount = new AtomicReference<>(0L); @@ -243,7 +257,7 @@ private Pair, Long> getAlterationCount profiledCasesCount.updateAndGet(v -> v + studyProfiledCasesCount); } studyAlterationCountByGenes.forEach(datum -> { - String key = keyGenerator.apply(datum); + String key = datum.getUniqueEventKey(); if (totalResult.containsKey(key)) { S alterationCountByGene = totalResult.get(key); alterationCountByGene.setTotalCount(alterationCountByGene.getTotalCount() + datum.getTotalCount()); diff --git a/service/src/main/java/org/cbioportal/service/impl/AlterationEnrichmentServiceImpl.java b/service/src/main/java/org/cbioportal/service/impl/AlterationEnrichmentServiceImpl.java index a0618736c7d..cbe49e76429 100644 --- a/service/src/main/java/org/cbioportal/service/impl/AlterationEnrichmentServiceImpl.java +++ b/service/src/main/java/org/cbioportal/service/impl/AlterationEnrichmentServiceImpl.java @@ -46,7 +46,7 @@ public Map, Long>> getAlterationCountsb if (enrichmentType.equals(EnrichmentType.SAMPLE)) { return alterationCountService - .getSampleAlterationCounts( + .getSampleAlterationGeneCounts( entry.getValue(), Select.all(), true, @@ -54,7 +54,7 @@ public Map, Long>> getAlterationCountsb alterationFilter); } else { return alterationCountService - .getPatientAlterationCounts( + .getPatientAlterationGeneCounts( entry.getValue(), Select.all(), true, diff --git a/service/src/main/java/org/cbioportal/service/impl/ClinicalDataServiceImpl.java b/service/src/main/java/org/cbioportal/service/impl/ClinicalDataServiceImpl.java index 1d786d09b55..a4d41a8f343 100644 --- a/service/src/main/java/org/cbioportal/service/impl/ClinicalDataServiceImpl.java +++ b/service/src/main/java/org/cbioportal/service/impl/ClinicalDataServiceImpl.java @@ -1,6 +1,5 @@ package org.cbioportal.service.impl; -import org.apache.commons.collections4.list.UnmodifiableList; import org.cbioportal.model.*; import org.cbioportal.model.meta.BaseMeta; import org.cbioportal.persistence.ClinicalDataRepository; @@ -228,10 +227,17 @@ public List getPatientClinicalDataDetailedToSample(List st } @Override - public List fetchSampleClinicalDataClinicalTable(List studyIds, List sampleIds, Integer pageSize, - Integer pageNumber, String searchTerm, String sortBy, - String direction) { - return clinicalDataRepository.fetchSampleClinicalDataClinicalTable(studyIds, sampleIds, pageSize, pageNumber, searchTerm, + public List fetchSampleClinicalTable(List studyIds, List sampleIds, Integer pageSize, + Integer pageNumber, String searchTerm, String sortBy, + String direction) { + return clinicalDataRepository.fetchSampleClinicalTable(studyIds, sampleIds, pageSize, pageNumber, searchTerm, sortBy, direction); } + + @Override + public Integer fetchSampleClinicalTableCount(List studyIds, List sampleIds, + String searchTerm, String sortBy, String direction) { + return clinicalDataRepository.fetchSampleClinicalTableCount(studyIds, sampleIds, searchTerm, + sortBy, direction); + } } diff --git a/service/src/main/java/org/cbioportal/service/impl/CustomDataServiceImpl.java b/service/src/main/java/org/cbioportal/service/impl/CustomDataServiceImpl.java new file mode 100644 index 00000000000..ef7c11c4889 --- /dev/null +++ b/service/src/main/java/org/cbioportal/service/impl/CustomDataServiceImpl.java @@ -0,0 +1,58 @@ +package org.cbioportal.service.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.cbioportal.service.CustomDataService; +import org.cbioportal.service.util.CustomDataSession; +import org.cbioportal.service.util.SessionServiceRequestHandler; +import org.cbioportal.session_service.domain.SessionType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +@Service +public class CustomDataServiceImpl implements CustomDataService { + @Autowired + private SessionServiceRequestHandler sessionServiceRequestHandler; + + @Autowired + private ObjectMapper sessionServiceObjectMapper; + + /** + * Retrieve CustomDataSession from session service for custom data attributes. + * @param customAttributeIds - attribute id/hash of custom data used as session service key. + * @return Map of custom data attribute id to the CustomDataSession + */ + @Override + public Map getCustomDataSessions(List customAttributeIds) { + Map> postFuturesMap = customAttributeIds.stream() + .collect(Collectors.toMap( + attributeId -> attributeId, + attributeId -> CompletableFuture.supplyAsync(() -> { + try { + String customDataSessionJson = sessionServiceRequestHandler.getSessionDataJson( + SessionType.custom_data, + attributeId + ); + return sessionServiceObjectMapper.readValue(customDataSessionJson, CustomDataSession.class); + } catch (Exception e) { + return null; + } + }) + )); + + CompletableFuture.allOf(postFuturesMap.values().toArray(new CompletableFuture[postFuturesMap.size()])).join(); + + Map customDataSessions = postFuturesMap.entrySet().stream() + .filter(entry -> entry.getValue().join() != null) + .collect(Collectors.toMap( + entry -> entry.getKey(), + entry -> entry.getValue().join() + )); + + return customDataSessions; + } +} diff --git a/service/src/main/java/org/cbioportal/service/impl/ExpressionEnrichmentServiceImpl.java b/service/src/main/java/org/cbioportal/service/impl/ExpressionEnrichmentServiceImpl.java index fb8fe8ef62a..45eb9ae478e 100644 --- a/service/src/main/java/org/cbioportal/service/impl/ExpressionEnrichmentServiceImpl.java +++ b/service/src/main/java/org/cbioportal/service/impl/ExpressionEnrichmentServiceImpl.java @@ -1,20 +1,23 @@ package org.cbioportal.service.impl; +import java.math.BigDecimal; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import org.apache.commons.lang3.BooleanUtils; +import org.cbioportal.model.MolecularProfile.MolecularAlterationType; +import org.cbioportal.model.meta.GenericAssayMeta; import org.cbioportal.model.EnrichmentType; -import org.cbioportal.model.Gene; -import org.cbioportal.model.GeneMolecularAlteration; -import org.cbioportal.model.GenericAssayEnrichment; +import org.cbioportal.model.GenericAssayBinaryEnrichment; +import org.cbioportal.model.GenericAssayCategoricalEnrichment; import org.cbioportal.model.GenericAssayMolecularAlteration; -import org.cbioportal.model.GenomicEnrichment; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfile.MolecularAlterationType; import org.cbioportal.model.MolecularProfileCaseIdentifier; +import org.cbioportal.model.MolecularProfile; import org.cbioportal.model.Sample; -import org.cbioportal.model.meta.GenericAssayMeta; +import org.cbioportal.model.GenericAssayEnrichment; +import org.cbioportal.model.GenomicEnrichment; +import org.cbioportal.model.Gene; +import org.cbioportal.model.GeneMolecularAlteration; import org.cbioportal.persistence.MolecularDataRepository; import org.cbioportal.service.ExpressionEnrichmentService; import org.cbioportal.service.GeneService; @@ -23,6 +26,7 @@ import org.cbioportal.service.SampleService; import org.cbioportal.service.exception.MolecularProfileNotFoundException; import org.cbioportal.service.util.ExpressionEnrichmentUtil; +import org.cbioportal.service.util.FisherExactTestCalculator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -42,68 +46,56 @@ public class ExpressionEnrichmentServiceImpl implements ExpressionEnrichmentServ private GenericAssayService genericAssayService; @Autowired private SampleService sampleService; - + @Autowired + private FisherExactTestCalculator fisherExactTestCalculator = new FisherExactTestCalculator(); @Override // transaction needs to be setup here in order to return Iterable from // molecularDataService in fetchCoExpressions @Transactional(readOnly = true) public List getGenomicEnrichments(String molecularProfileId, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType) - throws MolecularProfileNotFoundException { - + Map> molecularProfileCaseSets, EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException { MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - List validGenomicMolecularAlterationTypes = Arrays.asList( - MolecularAlterationType.MICRO_RNA_EXPRESSION, MolecularAlterationType.MRNA_EXPRESSION, - MolecularAlterationType.MRNA_EXPRESSION_NORMALS, MolecularAlterationType.RNA_EXPRESSION, - MolecularAlterationType.METHYLATION, MolecularAlterationType.METHYLATION_BINARY, - MolecularAlterationType.PHOSPHORYLATION, MolecularAlterationType.PROTEIN_LEVEL, - MolecularAlterationType.PROTEIN_ARRAY_PROTEIN_LEVEL, - MolecularAlterationType.PROTEIN_ARRAY_PHOSPHORYLATION); - + MolecularAlterationType.MICRO_RNA_EXPRESSION, MolecularAlterationType.MRNA_EXPRESSION, + MolecularAlterationType.MRNA_EXPRESSION_NORMALS, MolecularAlterationType.RNA_EXPRESSION, + MolecularAlterationType.METHYLATION, MolecularAlterationType.METHYLATION_BINARY, + MolecularAlterationType.PHOSPHORYLATION, MolecularAlterationType.PROTEIN_LEVEL, + MolecularAlterationType.PROTEIN_ARRAY_PROTEIN_LEVEL, + MolecularAlterationType.PROTEIN_ARRAY_PHOSPHORYLATION); validateMolecularProfile(molecularProfile, validGenomicMolecularAlterationTypes); - Iterable maItr = molecularDataRepository - .getGeneMolecularAlterationsIterableFast(molecularProfile.getStableId()); - + .getGeneMolecularAlterationsIterableFast(molecularProfile.getStableId()); List expressionEnrichments = expressionEnrichmentUtil.getEnrichments(molecularProfile, - molecularProfileCaseSets, enrichmentType, maItr); - + molecularProfileCaseSets, enrichmentType, maItr); List entrezGeneIds = expressionEnrichments.stream().map(GenomicEnrichment::getEntrezGeneId) - .collect(Collectors.toList()); - + .collect(Collectors.toList()); Map> geneMapByEntrezId = geneService - .fetchGenes(entrezGeneIds.stream().map(Object::toString).collect(Collectors.toList()), "ENTREZ_GENE_ID", - "SUMMARY") - .stream().collect(Collectors.groupingBy(Gene::getEntrezGeneId)); - + .fetchGenes(entrezGeneIds.stream().map(Object::toString).collect(Collectors.toList()), "ENTREZ_GENE_ID", + "SUMMARY") + .stream().collect(Collectors.groupingBy(Gene::getEntrezGeneId)); return expressionEnrichments.stream() - // filter Enrichments having no gene reference object(this - // happens when multiple - // entrez ids map to same hugo gene symbol) - .filter(expressionEnrichment -> geneMapByEntrezId.containsKey(expressionEnrichment.getEntrezGeneId())) - .map(expressionEnrichment -> { - Gene gene = geneMapByEntrezId.get(expressionEnrichment.getEntrezGeneId()).get(0); - expressionEnrichment.setHugoGeneSymbol(gene.getHugoGeneSymbol()); - return expressionEnrichment; - }).collect(Collectors.toList()); + // filter Enrichments having no gene reference object(this + // happens when multiple + // entrez ids map to same hugo gene symbol) + .filter(expressionEnrichment -> geneMapByEntrezId.containsKey(expressionEnrichment.getEntrezGeneId())) + .map(expressionEnrichment -> { + Gene gene = geneMapByEntrezId.get(expressionEnrichment.getEntrezGeneId()).get(0); + expressionEnrichment.setHugoGeneSymbol(gene.getHugoGeneSymbol()); + return expressionEnrichment; + }).collect(Collectors.toList()); } - @Override // transaction needs to be setup here in order to return Iterable from // molecularDataRepository in getGenericAssayMolecularAlterationsIterable @Transactional(readOnly = true) - public List getGenericAssayEnrichments(String molecularProfileId, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType) - throws MolecularProfileNotFoundException { - + public List getGenericAssayNumericalEnrichments(String molecularProfileId, + Map> molecularProfileCaseSets, EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException { MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - validateMolecularProfile(molecularProfile, Arrays.asList(MolecularAlterationType.GENERIC_ASSAY)); - Iterable maItr = molecularDataRepository - .getGenericAssayMolecularAlterationsIterable(molecularProfile.getStableId(), null, "SUMMARY"); - + .getGenericAssayMolecularAlterationsIterable(molecularProfile.getStableId(), null, "SUMMARY"); Map> filteredMolecularProfileCaseSets; if (BooleanUtils.isTrue(molecularProfile.getPatientLevel())) { // Build sampleIdToPatientIdMap to quick find if a sample has shared patientId with other samples @@ -125,31 +117,159 @@ public List getGenericAssayEnrichments(String molecularP filteredMolecularProfileCaseSets.put(pair.getKey(), identifierListUniqueByPatientId); } } else { - filteredMolecularProfileCaseSets = molecularProfileCaseSets; + filteredMolecularProfileCaseSets = molecularProfileCaseSets; } List genericAssayEnrichments = expressionEnrichmentUtil.getEnrichments(molecularProfile, - filteredMolecularProfileCaseSets, enrichmentType, maItr); + filteredMolecularProfileCaseSets, enrichmentType, maItr); List getGenericAssayStableIds = genericAssayEnrichments.stream() - .map(GenericAssayEnrichment::getStableId).collect(Collectors.toList()); + .map(GenericAssayEnrichment::getStableId).collect(Collectors.toList()); Map genericAssayMetaByStableId = genericAssayService - .getGenericAssayMetaByStableIdsAndMolecularIds(getGenericAssayStableIds, - getGenericAssayStableIds.stream().map(stableId -> molecularProfileId) - .collect(Collectors.toList()), - "SUMMARY") - .stream().collect(Collectors.toMap(GenericAssayMeta::getStableId, Function.identity())); + .getGenericAssayMetaByStableIdsAndMolecularIds(getGenericAssayStableIds, + getGenericAssayStableIds.stream().map(stableId -> molecularProfileId) + .collect(Collectors.toList()), + "SUMMARY") + .stream().collect(Collectors.toMap(GenericAssayMeta::getStableId, Function.identity())); return genericAssayEnrichments.stream().map(enrichmentDatum -> { enrichmentDatum.setGenericEntityMetaProperties( - genericAssayMetaByStableId.get(enrichmentDatum.getStableId()).getGenericEntityMetaProperties()); + genericAssayMetaByStableId.get(enrichmentDatum.getStableId()).getGenericEntityMetaProperties()); return enrichmentDatum; }).collect(Collectors.toList()); } + @Override + @Transactional(readOnly = true) + public List getGenericAssayBinaryEnrichments( + String molecularProfileId, + Map> molecularProfileCaseSets, EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException { + + // Validate and fetch molecular profile + MolecularProfile molecularProfile = getAndValidateMolecularProfile(molecularProfileId, "BINARY"); + + // Get the molecular alterations for the provided profile + Iterable maItr = molecularDataRepository + .getGenericAssayMolecularAlterationsIterable(molecularProfile.getStableId(), null, "SUMMARY"); + + // Filter the case sets based on molecular profile + Map> filteredMolecularProfileCaseSets = filterMolecularProfileCaseSets(molecularProfile, molecularProfileCaseSets); + + // Obtain binary enrichments from the utility + List genericAssayBinaryEnrichments = expressionEnrichmentUtil.getGenericAssayBinaryEnrichments(molecularProfile, + filteredMolecularProfileCaseSets, enrichmentType, maItr); + + // Calculate q-values for enrichments + calcQValues(genericAssayBinaryEnrichments); + + // Extract stable IDs from binary enrichments + List getGenericAssayStableIds = genericAssayBinaryEnrichments.stream() + .map(GenericAssayEnrichment::getStableId).collect(Collectors.toList()); + + // Fetch metadata of generic assays by their stable IDs + Map genericAssayMetaByStableId = getGenericAssayMetaByStableId(getGenericAssayStableIds, molecularProfileId); + + // Assign meta properties to each enrichment + return genericAssayBinaryEnrichments.stream().map(enrichmentDatum -> { + enrichmentDatum.setGenericEntityMetaProperties( + genericAssayMetaByStableId.get(enrichmentDatum.getStableId()).getGenericEntityMetaProperties()); + return enrichmentDatum; + }).collect(Collectors.toList()); + } + + @Override + @Transactional(readOnly = true) + public List getGenericAssayCategoricalEnrichments(String molecularProfileId, + Map> molecularProfileCaseSets, EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = getAndValidateMolecularProfile(molecularProfileId, "CATEGORICAL"); + + Iterable maItr = molecularDataRepository + .getGenericAssayMolecularAlterationsIterable(molecularProfile.getStableId(), null, "SUMMARY"); + + Map> filteredMolecularProfileCaseSets = filterMolecularProfileCaseSets(molecularProfile, molecularProfileCaseSets); + + List genericAssayCategoricalEnrichments = expressionEnrichmentUtil.getGenericAssayCategoricalEnrichments(molecularProfile, + filteredMolecularProfileCaseSets, enrichmentType, maItr); + + calcQValues(genericAssayCategoricalEnrichments); + + List getGenericAssayStableIds = genericAssayCategoricalEnrichments.stream() + .map(GenericAssayEnrichment::getStableId).collect(Collectors.toList()); + Map genericAssayMetaByStableId = getGenericAssayMetaByStableId(getGenericAssayStableIds, molecularProfileId); + + return genericAssayCategoricalEnrichments.stream().map(enrichmentDatum -> { + enrichmentDatum.setGenericEntityMetaProperties( + genericAssayMetaByStableId.get(enrichmentDatum.getStableId()).getGenericEntityMetaProperties()); + return enrichmentDatum; + }).collect(Collectors.toList()); + } + + private MolecularProfile getAndValidateMolecularProfile(String molecularProfileId, String dataType) throws MolecularProfileNotFoundException { + MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); + validateMolecularProfile(molecularProfile, Arrays.asList(MolecularProfile.MolecularAlterationType.GENERIC_ASSAY), dataType); + return molecularProfile; + } private void validateMolecularProfile(MolecularProfile molecularProfile, - List validMolecularAlterationTypes) throws MolecularProfileNotFoundException { + List validMolecularAlterationTypes, + String dataType) throws MolecularProfileNotFoundException { if (!validMolecularAlterationTypes.contains(molecularProfile.getMolecularAlterationType())) { + // Check alteration type throw new MolecularProfileNotFoundException(molecularProfile.getStableId()); } + // Check datatype for binary or categorical + if(molecularProfile.getMolecularAlterationType().equals(MolecularProfile.MolecularAlterationType.GENERIC_ASSAY) && + !molecularProfile.getDatatype().equals(dataType)) + throw new MolecularProfileNotFoundException(molecularProfile.getStableId()); + } + + private Map> filterMolecularProfileCaseSets(MolecularProfile molecularProfile, Map> molecularProfileCaseSets) { + if (BooleanUtils.isTrue(molecularProfile.getPatientLevel())) { + // If patient level, filter duplicates by patient id + // For now we only support sample level for samples + List sampleIds = molecularProfileCaseSets.values().stream().flatMap(Collection::stream).map(MolecularProfileCaseIdentifier::getCaseId).collect(Collectors.toList()); + List studyIds = Collections.nCopies(sampleIds.size(), molecularProfile.getCancerStudyIdentifier()); + List samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); + Map sampleIdToPatientIdMap = samples.stream().collect(Collectors.toMap(Sample::getStableId, Sample::getPatientId)); + + Map> filteredMolecularProfileCaseSets = new HashMap<>(); + for (Map.Entry> pair : molecularProfileCaseSets.entrySet()) { + Set patientSet = new HashSet(); + List identifierListUniqueByPatientId = new ArrayList<>(); + for (MolecularProfileCaseIdentifier caseIdentifier : pair.getValue()) { + if (!patientSet.contains(sampleIdToPatientIdMap.get(caseIdentifier.getCaseId()))) { + identifierListUniqueByPatientId.add(caseIdentifier); + patientSet.add(sampleIdToPatientIdMap.get(caseIdentifier.getCaseId())); + } + } + filteredMolecularProfileCaseSets.put(pair.getKey(), identifierListUniqueByPatientId); + } + return filteredMolecularProfileCaseSets; + } else { + return molecularProfileCaseSets; + } + } + + private Map getGenericAssayMetaByStableId(List stableIds, String molecularProfileId) { + return genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds(stableIds, stableIds.stream().map(sid -> molecularProfileId) + .collect(Collectors.toList()), "SUMMARY").stream() + .collect(Collectors.toMap(GenericAssayMeta::getStableId, Function.identity())); } + private void calcQValues(List enrichments) { + // Sort enrichments by pValue + Collections.sort(enrichments, GenericAssayEnrichment::compare); + BigDecimal[] pValues = enrichments.stream().map(T::getpValue).toArray(BigDecimal[]::new); + BigDecimal[] qValues = fisherExactTestCalculator.calcqValue(pValues); + // Assign q-values to enrichments + for (int i = 0; i < enrichments.size(); i++) { + enrichments.get(i).setqValue(qValues[i]); + } + } + private void validateMolecularProfile(MolecularProfile molecularProfile, + List validMolecularAlterationTypes) throws MolecularProfileNotFoundException { + if (!validMolecularAlterationTypes.contains(molecularProfile.getMolecularAlterationType())) { + throw new MolecularProfileNotFoundException(molecularProfile.getStableId()); + } + } } diff --git a/service/src/main/java/org/cbioportal/service/impl/StructuralVariantServiceImpl.java b/service/src/main/java/org/cbioportal/service/impl/StructuralVariantServiceImpl.java index 004caf5d698..bbb420b2b2d 100644 --- a/service/src/main/java/org/cbioportal/service/impl/StructuralVariantServiceImpl.java +++ b/service/src/main/java/org/cbioportal/service/impl/StructuralVariantServiceImpl.java @@ -24,6 +24,7 @@ package org.cbioportal.service.impl; import org.cbioportal.model.GeneFilterQuery; +import org.cbioportal.model.StructuralVariantFilterQuery; import org.cbioportal.model.StructuralVariant; import org.cbioportal.model.StructuralVariantQuery; import org.cbioportal.persistence.StructuralVariantRepository; @@ -59,4 +60,12 @@ public List fetchStructuralVariantsByGeneQueries(List molecularProfileIds, sampleIds, geneQueries); } + @Override + public List fetchStructuralVariantsByStructVarQueries(List molecularProfileIds, + List sampleIds, + List structVarQueries) { + return structuralVariantRepository.fetchStructuralVariantsByStructVarQueries( + molecularProfileIds, sampleIds, structVarQueries); + } + } diff --git a/service/src/main/java/org/cbioportal/service/impl/StudyViewServiceImpl.java b/service/src/main/java/org/cbioportal/service/impl/StudyViewServiceImpl.java index 3099ab9327d..510fa8f0206 100644 --- a/service/src/main/java/org/cbioportal/service/impl/StudyViewServiceImpl.java +++ b/service/src/main/java/org/cbioportal/service/impl/StudyViewServiceImpl.java @@ -2,8 +2,10 @@ import org.apache.commons.collections4.map.MultiKeyMap; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.math3.util.Pair; import org.cbioportal.model.*; import org.cbioportal.model.util.Select; +import org.cbioportal.persistence.AlterationRepository; import org.cbioportal.service.*; import org.cbioportal.service.exception.MolecularProfileNotFoundException; import org.cbioportal.service.exception.StudyNotFoundException; @@ -14,6 +16,7 @@ import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; @Service public class StudyViewServiceImpl implements StudyViewService { @@ -33,6 +36,15 @@ public class StudyViewServiceImpl implements StudyViewService { @Autowired private GenericAssayService genericAssayService; + @Autowired + private AlterationRepository alterationRepository; + + @Autowired + private GeneService geneService; + + @Autowired + private MolecularDataService molecularDataService; + @Override public List getGenomicDataCounts(List studyIds, List sampleIds) { List molecularProfileSampleIdentifiers = @@ -82,7 +94,7 @@ public List getMutationAlterationCountByGenes(List caseIdentifiers = molecularProfileService.getFirstMutationProfileCaseIdentifiers(studyIds, sampleIds); - List alterationCountByGenes = alterationCountService.getSampleMutationCounts( + List alterationCountByGenes = alterationCountService.getSampleMutationGeneCounts( caseIdentifiers, Select.all(), true, @@ -99,7 +111,7 @@ public List getStructuralVariantAlterationCountByGenes(Li throws StudyNotFoundException { List caseIdentifiers = molecularProfileService.getFirstStructuralVariantProfileCaseIdentifiers(studyIds, sampleIds); - List alterationCountByGenes = alterationCountService.getSampleStructuralVariantCounts( + List alterationCountByGenes = alterationCountService.getSampleStructuralVariantGeneCounts( caseIdentifiers, Select.all(), true, @@ -109,6 +121,18 @@ public List getStructuralVariantAlterationCountByGenes(Li return alterationCountByGenes; } + @Override + public List getStructuralVariantAlterationCounts(List studyIds, + List sampleIds, + AlterationFilter annotationFilters) { + List caseIdentifiers = + molecularProfileService.getFirstStructuralVariantProfileCaseIdentifiers(studyIds, sampleIds); + return alterationCountService.getSampleStructuralVariantCounts(caseIdentifiers, + true, + false, + annotationFilters).getFirst(); + } + private void annotateDataWithQValue(List studyIds, List alterationCountByGenes) throws StudyNotFoundException { Set distinctStudyIds = new HashSet<>(studyIds); @@ -138,8 +162,8 @@ public List getCNAAlterationCountByGenes(List stu throws StudyNotFoundException { List caseIdentifiers = molecularProfileService.getFirstDiscreteCNAProfileCaseIdentifiers(studyIds, sampleIds); - Select cnaTypes = Select.byValues(CNA_TYPES_AMP_AND_HOMDEL); - List copyNumberCountByGenes = alterationCountService.getSampleCnaCounts( + + List copyNumberCountByGenes = alterationCountService.getSampleCnaGeneCounts( caseIdentifiers, Select.all(), true, @@ -170,6 +194,96 @@ public List getCNAAlterationCountByGenes(List stu return copyNumberCountByGenes; } + @Override + public List getCNAAlterationCountsByGeneSpecific(List studyIds, + List sampleIds, + List> genomicDataFilters) { + + List molecularProfiles = molecularProfileService.getMolecularProfilesInStudies(studyIds, + "SUMMARY"); + + Map> molecularProfileMap = molecularProfileUtil + .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); + + Set hugoGeneSymbols = genomicDataFilters.stream().map(Pair::getKey) + .collect(Collectors.toSet()); + + Map geneSymbolIdMap = geneService + .fetchGenes(new ArrayList<>(hugoGeneSymbols), "HUGO_GENE_SYMBOL", + "SUMMARY") + .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + return genomicDataFilters + .stream() + .flatMap(gdFilter -> { + GenomicDataCountItem genomicDataCountItem = new GenomicDataCountItem(); + String hugoGeneSymbol = gdFilter.getKey(); + String profileType = gdFilter.getValue(); + genomicDataCountItem.setHugoGeneSymbol(hugoGeneSymbol); + genomicDataCountItem.setProfileType(profileType); + + List stableIds = Arrays.asList(geneSymbolIdMap.get(hugoGeneSymbol).toString()); + + Map studyIdToMolecularProfileIdMap = molecularProfileMap + .getOrDefault(profileType, new ArrayList()).stream() + .collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, + MolecularProfile::getStableId)); + + List mappedSampleIds = new ArrayList<>(); + List mappedProfileIds = new ArrayList<>(); + + for (int i = 0; i < sampleIds.size(); i++) { + String studyId = studyIds.get(i); + if (studyIdToMolecularProfileIdMap.containsKey(studyId)) { + mappedSampleIds.add(sampleIds.get(i)); + mappedProfileIds.add(studyIdToMolecularProfileIdMap.get(studyId)); + } + } + + if (mappedSampleIds.isEmpty()) { + return Stream.of(); + } + + List geneMolecularDataList = molecularDataService.getMolecularDataInMultipleMolecularProfiles(mappedProfileIds, mappedSampleIds, + stableIds.stream().map(Integer::parseInt).collect(Collectors.toList()), "SUMMARY"); + + List genomicDataCounts = geneMolecularDataList + .stream() + .filter(g -> StringUtils.isNotEmpty(g.getValue()) && !g.getValue().equals("NA")) + .collect(Collectors.groupingBy(GeneMolecularData::getValue)) + .entrySet() + .stream() + .map(entry -> { + Integer alteration = Integer.valueOf(entry.getKey()); + List geneMolecularData = entry.getValue(); + int count = geneMolecularData.size(); + + String label = CNA.getByCode(alteration.shortValue()).getDescription(); + + GenomicDataCount genomicDataCount = new GenomicDataCount(); + genomicDataCount.setLabel(label); + genomicDataCount.setValue(String.valueOf(alteration)); + genomicDataCount.setCount(count); + + return genomicDataCount; + }).collect(Collectors.toList()); + + int totalCount = genomicDataCounts.stream().mapToInt(GenomicDataCount::getCount).sum(); + int naCount = sampleIds.size() - totalCount; + + if (naCount > 0) { + GenomicDataCount genomicDataCount = new GenomicDataCount(); + genomicDataCount.setLabel("NA"); + genomicDataCount.setValue("NA"); + genomicDataCount.setCount(naCount); + genomicDataCounts.add(genomicDataCount); + } + + genomicDataCountItem.setCounts(genomicDataCounts); + return Stream.of(genomicDataCountItem); + }).collect(Collectors.toList()); + }; + @Override public List fetchGenericAssayDataCounts(List sampleIds, List studyIds, List stableIds, List profileTypes) { diff --git a/service/src/main/java/org/cbioportal/service/impl/TreatmentServiceImpl.java b/service/src/main/java/org/cbioportal/service/impl/TreatmentServiceImpl.java index 439f94ce20c..75784a01c15 100644 --- a/service/src/main/java/org/cbioportal/service/impl/TreatmentServiceImpl.java +++ b/service/src/main/java/org/cbioportal/service/impl/TreatmentServiceImpl.java @@ -12,8 +12,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static java.util.stream.Collectors.toList; - @Service public class TreatmentServiceImpl implements TreatmentService { @Autowired @@ -25,7 +23,7 @@ private Pair, List> filterIds(List sampleIds, List< } Set studiesWithTreatments = studyIds.stream() .distinct() - .filter(studyId -> treatmentRepository.studyIdHasTreatments(studyId, key)) + .filter(studyId -> treatmentRepository.hasTreatmentData(Collections.singletonList(studyId), key)) .collect(Collectors.toSet()); ArrayList filteredSampleIds = new ArrayList<>(); @@ -40,16 +38,16 @@ private Pair, List> filterIds(List sampleIds, List< } return new ImmutablePair<>(filteredSampleIds, filteredStudyIds); } - + @Override public List getAllSampleTreatmentRows(List sampleIds, List studyIds, ClinicalEventKeyCode key) { Pair, List> filteredIds = filterIds(sampleIds, studyIds, key); sampleIds = filteredIds.getLeft(); studyIds = filteredIds.getRight(); - Map> samplesByPatient = + Map> samplesByPatient = treatmentRepository.getSamplesByPatientId(sampleIds, studyIds); - Map> treatmentsByPatient = + Map> treatmentsByPatient = treatmentRepository.getTreatmentsByPatientId(sampleIds, studyIds, key); Stream rows = samplesByPatient.keySet().stream() @@ -150,7 +148,6 @@ Stream toRows() { ); } } - @Override public List getAllPatientTreatmentRows( List sampleIds, List studyIds, ClinicalEventKeyCode key @@ -158,63 +155,44 @@ public List getAllPatientTreatmentRows( Pair, List> filteredIds = filterIds(sampleIds, studyIds, key); sampleIds = filteredIds.getLeft(); studyIds = filteredIds.getRight(); - - Map> treatmentsByPatient = - treatmentRepository.getTreatmentsByPatientId(sampleIds, studyIds, key); - Map> samplesByPatient = treatmentRepository - .getShallowSamplesByPatientId(sampleIds, studyIds) - .entrySet() - .stream() - .filter(e -> treatmentsByPatient.containsKey(e.getKey())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - Set treatments = treatmentRepository.getAllUniqueTreatments(sampleIds, studyIds, key); - - return treatments.stream() - .map(t -> createPatientTreatmentRowForTreatment(t, treatmentsByPatient, samplesByPatient)) - .collect(Collectors.toList()); - } - private PatientTreatmentRow createPatientTreatmentRowForTreatment( - String treatment, - Map> treatmentsByPatient, - Map> samplesByPatient - ) { - // find all the patients that have received this treatment - List>> matchingPatients = matchingPatients(treatment, treatmentsByPatient); + Map> samplesByPatient = treatmentRepository + .getShallowSamplesByPatientId(sampleIds, studyIds); - // from those patients, extract the unique samples - Set samples = matchingPatients + Map> treatmentSet = treatmentRepository.getTreatments(sampleIds, studyIds, key) .stream() - .map(Map.Entry::getKey) - .flatMap(patient -> samplesByPatient.getOrDefault(patient, new ArrayList<>()).stream()) - .collect(Collectors.toSet()); - - - return new PatientTreatmentRow(treatment, matchingPatients.size(), samples); - } + .collect(Collectors.groupingBy(Treatment::getTreatment)); - private List>> matchingPatients( - String treatment, - Map> treatmentsByPatient - ) { - return treatmentsByPatient.entrySet().stream() - .filter(p -> p.getValue().stream().anyMatch(t -> t.getTreatment().equals(treatment))) - .collect(toList()); + /* + This logic transforms treatmentSet to list of PatientTreatmentRow. transformation steps: + - key in treatmentSet is going to be treatment + - get all unique patient ids -> this is going to give count + - get all clinicalEventSamples using above unique patient ids + */ + return treatmentSet.entrySet() + .stream() + .map(entry -> { + String treatment = entry.getKey(); + Set patientIds = entry.getValue().stream().map(Treatment::getPatientId).collect(Collectors.toSet()); + Set clinicalEventSamples = patientIds + .stream() + .flatMap(patientId -> samplesByPatient.getOrDefault(patientId, new ArrayList<>()).stream()) + .collect(Collectors.toSet()); + return new PatientTreatmentRow(treatment, patientIds.size(), clinicalEventSamples); + }) + .collect(Collectors.toList()); } @Override public Boolean containsTreatmentData(List studies, ClinicalEventKeyCode key) { - return treatmentRepository.getTreatmentCount(studies, key.getKey()) > 0; + return treatmentRepository.hasTreatmentData(studies, key); } @Override public Boolean containsSampleTreatmentData(List studyIds, ClinicalEventKeyCode key) { studyIds = studyIds.stream() - .filter(studyId -> treatmentRepository.studyIdHasTreatments(studyId, key)) + .filter(studyId -> treatmentRepository.hasTreatmentData(Collections.singletonList(studyId), key)) .collect(Collectors.toList()); - Integer sampleCount = treatmentRepository.getSampleCount(studyIds); - Integer treatmentCount = treatmentRepository.getTreatmentCount(studyIds, key.getKey()); - - return sampleCount * treatmentCount > 0; + return studyIds.size() > 0 && treatmentRepository.hasSampleTimelineData(studyIds); } } diff --git a/service/src/main/java/org/cbioportal/service/util/AlterationEnrichmentUtil.java b/service/src/main/java/org/cbioportal/service/util/AlterationEnrichmentUtil.java index 7bc9e46c5c9..8113cc63f73 100644 --- a/service/src/main/java/org/cbioportal/service/util/AlterationEnrichmentUtil.java +++ b/service/src/main/java/org/cbioportal/service/util/AlterationEnrichmentUtil.java @@ -2,6 +2,7 @@ import org.apache.commons.math3.stat.inference.ChiSquareTest; import org.apache.commons.math3.util.Pair; +import org.cbioportal.model.AlterationCountBase; import org.cbioportal.model.AlterationCountByGene; import org.cbioportal.model.AlterationEnrichment; import org.cbioportal.model.CountSummary; @@ -28,7 +29,7 @@ import java.util.Map.Entry; @Component -public class AlterationEnrichmentUtil { +public class AlterationEnrichmentUtil { @Autowired private FisherExactTestCalculator fisherExactTestCalculator; @@ -41,7 +42,7 @@ public class AlterationEnrichmentUtil { @Autowired private MolecularProfileService molecularProfileService; - public List createAlterationEnrichments(Map, Long>> mutationCountsbyGroup) { + public List createAlterationEnrichments(Map, Long>> mutationCountsbyGroup) { Map> mutationCountsbyEntrezGeneIdAndGroup = mutationCountsbyGroup .entrySet() @@ -131,7 +132,7 @@ public List createAlterationEnrichments(Map createAlterationEnrichments(Map molecularProfileCaseIdentifiers, - List alterationCountByGenes, + List alterationCounts, boolean includeMissingAlterationsFromGenePanel) { // Collect profile id and sample id arrays. // These are arrays of equal length, where every index // represents a sample id / profile id-combination List sampleIds = new ArrayList<>(); - List molecularProfileIds = new ArrayList<>(); + List molecularProfileIds = new ArrayList<>(); molecularProfileCaseIdentifiers.forEach(pair -> { sampleIds.add(pair.getCaseId()); molecularProfileIds.add(pair.getMolecularProfileId()); @@ -176,7 +177,7 @@ public long includeFrequencyForSamples( List genePanelDataList = genePanelService .fetchGenePanelDataInMultipleMolecularProfiles(molecularProfileCaseIdentifiers); - profiledCasesCounter.calculate(alterationCountByGenes, genePanelDataList, + profiledCasesCounter.calculate(alterationCounts, genePanelDataList, includeMissingAlterationsFromGenePanel, profiledCasesCounter.sampleUniqueIdentifier); return genePanelDataList @@ -189,7 +190,7 @@ public long includeFrequencyForSamples( public long includeFrequencyForPatients( List molecularProfileCaseIdentifiers, - List alterationCountByGenes, + List alterationCounts, boolean includeMissingAlterationsFromGenePanel) { // Collect profile id and sample id arrays. @@ -205,7 +206,7 @@ public long includeFrequencyForPatients( List genePanelDataList = genePanelService .fetchGenePanelDataInMultipleMolecularProfilesByPatientIds(molecularProfileCaseIdentifiers); - profiledCasesCounter.calculate(alterationCountByGenes, genePanelDataList, + profiledCasesCounter.calculate(alterationCounts, genePanelDataList, includeMissingAlterationsFromGenePanel, profiledCasesCounter.patientUniqueIdentifier); return genePanelDataList diff --git a/service/src/main/java/org/cbioportal/service/util/BinnableCustomDataValue.java b/service/src/main/java/org/cbioportal/service/util/BinnableCustomDataValue.java new file mode 100644 index 00000000000..a8b07f0dd4a --- /dev/null +++ b/service/src/main/java/org/cbioportal/service/util/BinnableCustomDataValue.java @@ -0,0 +1,49 @@ +package org.cbioportal.service.util; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import org.cbioportal.model.Binnable; + +import java.io.Serializable; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class BinnableCustomDataValue implements Binnable, Serializable { + + private final CustomDataValue customDataValue; + private final String attrId; + private final Boolean patientAttribute; + + public BinnableCustomDataValue( + CustomDataValue customDataValue, + String attributeId, + Boolean patientAttribute + ) { + this.customDataValue = customDataValue; + this.attrId = attributeId; + this.patientAttribute = patientAttribute; + } + + public String getSampleId() { + return customDataValue.getSampleId(); + } + + public String getPatientId() { + return customDataValue.getPatientId(); + } + + public String getStudyId() { + return customDataValue.getStudyId(); + } + + public String getAttrId() { + return attrId; + } + + public Boolean isPatientAttribute() { + return patientAttribute; + } + + public String getAttrValue() { + return customDataValue.getValue(); + } + +} diff --git a/service/src/main/java/org/cbioportal/service/util/ClinicalAttributeUtil.java b/service/src/main/java/org/cbioportal/service/util/ClinicalAttributeUtil.java index 1a5996054f3..fc64d5b8d58 100644 --- a/service/src/main/java/org/cbioportal/service/util/ClinicalAttributeUtil.java +++ b/service/src/main/java/org/cbioportal/service/util/ClinicalAttributeUtil.java @@ -11,17 +11,24 @@ @Component public class ClinicalAttributeUtil { - public void extractCategorizedClinicalAttributes(List clinicalAttributes, - List sampleAttributeIds, List patientAttributeIds, - List conflictingPatientAttributeIds) { - + + public void extractCategorizedClinicalAttributes( + List clinicalAttributes, + List sampleAttributeIds, + List patientAttributeIds, + List conflictingPatientAttributeIds + ) { + Set sampleAttributeIdsSet = new HashSet(); Set patientAttributeIdsSet = new HashSet(); Set conflictingPatientAttributeIdsSet = new HashSet(); - Map>> groupedAttributesByIdAndType = clinicalAttributes.stream() - .collect(Collectors.groupingBy(ClinicalAttribute::getAttrId, - Collectors.groupingBy(ClinicalAttribute::getPatientAttribute))); + Map>> groupedAttributesByIdAndType = clinicalAttributes + .stream() + .collect(Collectors.groupingBy( + ClinicalAttribute::getAttrId, + Collectors.groupingBy(ClinicalAttribute::getPatientAttribute) + )); groupedAttributesByIdAndType.entrySet().forEach(entry -> { if (entry.getValue().keySet().size() == 1) { @@ -42,7 +49,7 @@ public void extractCategorizedClinicalAttributes(List clinica }); } }); - + sampleAttributeIds.addAll(sampleAttributeIdsSet); patientAttributeIds.addAll(patientAttributeIdsSet); conflictingPatientAttributeIds.addAll(conflictingPatientAttributeIdsSet); diff --git a/web/src/main/java/org/cbioportal/web/CustomAttributeWithData.java b/service/src/main/java/org/cbioportal/service/util/CustomAttributeWithData.java similarity index 93% rename from web/src/main/java/org/cbioportal/web/CustomAttributeWithData.java rename to service/src/main/java/org/cbioportal/service/util/CustomAttributeWithData.java index 657a6424fc1..65b7758d573 100644 --- a/web/src/main/java/org/cbioportal/web/CustomAttributeWithData.java +++ b/service/src/main/java/org/cbioportal/service/util/CustomAttributeWithData.java @@ -1,18 +1,18 @@ -package org.cbioportal.web; +package org.cbioportal.service.util; import java.io.Serializable; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import javax.validation.constraints.NotNull; -import org.cbioportal.web.parameter.CustomDataValue; - import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) -public class CustomAttributeWithData implements Serializable{ +public class CustomAttributeWithData implements Serializable { private String owner = "anonymous"; private Set origin = new HashSet<>(); diff --git a/web/src/main/java/org/cbioportal/web/parameter/CustomDataSession.java b/service/src/main/java/org/cbioportal/service/util/CustomDataSession.java similarity index 93% rename from web/src/main/java/org/cbioportal/web/parameter/CustomDataSession.java rename to service/src/main/java/org/cbioportal/service/util/CustomDataSession.java index 61cb4d32275..cd25a4ea471 100644 --- a/web/src/main/java/org/cbioportal/web/parameter/CustomDataSession.java +++ b/service/src/main/java/org/cbioportal/service/util/CustomDataSession.java @@ -1,4 +1,4 @@ -package org.cbioportal.web.parameter; +package org.cbioportal.service.util; import java.io.IOException; @@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory; import org.cbioportal.session_service.domain.Session; import org.cbioportal.session_service.domain.SessionType; -import org.cbioportal.web.CustomAttributeWithData; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/web/src/main/java/org/cbioportal/web/parameter/CustomDataValue.java b/service/src/main/java/org/cbioportal/service/util/CustomDataValue.java similarity index 96% rename from web/src/main/java/org/cbioportal/web/parameter/CustomDataValue.java rename to service/src/main/java/org/cbioportal/service/util/CustomDataValue.java index 57960a551a7..a0cb95c42a6 100644 --- a/web/src/main/java/org/cbioportal/web/parameter/CustomDataValue.java +++ b/service/src/main/java/org/cbioportal/service/util/CustomDataValue.java @@ -1,4 +1,4 @@ -package org.cbioportal.web.parameter; +package org.cbioportal.service.util; import java.io.Serializable; diff --git a/service/src/main/java/org/cbioportal/service/util/ExpressionEnrichmentUtil.java b/service/src/main/java/org/cbioportal/service/util/ExpressionEnrichmentUtil.java index a147e0065fc..2fedb6eb5dd 100644 --- a/service/src/main/java/org/cbioportal/service/util/ExpressionEnrichmentUtil.java +++ b/service/src/main/java/org/cbioportal/service/util/ExpressionEnrichmentUtil.java @@ -3,29 +3,36 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; -import java.util.List; +import java.util.HashMap; import java.util.Map; +import java.util.Set; +import java.util.List; import java.util.Map.Entry; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.math3.stat.StatUtils; -import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; -import org.apache.commons.math3.stat.inference.OneWayAnova; -import org.apache.commons.math3.stat.inference.TestUtils; import org.cbioportal.model.EnrichmentType; import org.cbioportal.model.ExpressionEnrichment; import org.cbioportal.model.GenericAssayEnrichment; +import org.cbioportal.model.GenericAssayBinaryEnrichment; +import org.cbioportal.model.GenericAssayCategoricalEnrichment; import org.cbioportal.model.GenericAssayMolecularAlteration; import org.cbioportal.model.GenomicEnrichment; import org.cbioportal.model.GroupStatistics; +import org.cbioportal.model.GenericAssayCountSummary; import org.cbioportal.model.MolecularAlteration; import org.cbioportal.model.MolecularProfile; import org.cbioportal.model.MolecularProfileCaseIdentifier; import org.cbioportal.model.MolecularProfileSamples; import org.cbioportal.model.Sample; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.math3.stat.StatUtils; +import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; +import org.apache.commons.math3.stat.inference.ChiSquareTest; +import org.apache.commons.math3.stat.inference.OneWayAnova; +import org.apache.commons.math3.stat.inference.TestUtils; import org.cbioportal.persistence.MolecularDataRepository; import org.cbioportal.service.SampleService; import org.springframework.beans.factory.annotation.Autowired; @@ -34,199 +41,376 @@ @Component public class ExpressionEnrichmentUtil { - @Autowired - private SampleService sampleService; - @Autowired - private MolecularDataRepository molecularDataRepository; - - private static final double LOG2 = Math.log(2); - private static final String RNA_SEQ = "rna_seq"; - - public List getEnrichments( - MolecularProfile molecularProfile, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType, - Iterable maItr) { - List expressionEnrichments = new ArrayList<>(); - - Map> groupIndicesMap = getGroupIndicesMap(molecularProfileCaseSets, enrichmentType, - molecularProfile); - for (MolecularAlteration ma : maItr) { - - List groupsStatistics = new ArrayList(); - // used for p-value calculation - List groupedValues = new ArrayList(); - - for (Entry> group : groupIndicesMap.entrySet()) { - - // get expression values to all the indices in the group - List molecularDataValues = group.getValue().stream() - .map(sampleIndex -> ma.getSplitValues()[sampleIndex]) - .filter(a -> NumberUtils.isNumber(a)) - .collect(Collectors.toList()); - - // ignore group if there are less than 2 values - if (molecularDataValues.size() < 2) { - continue; - } - - double[] values = getAlterationValues(molecularDataValues, molecularProfile.getStableId()); - - GroupStatistics groupStatistics = new GroupStatistics(); - double alteredMean = StatUtils.mean(values); - double alteredStandardDeviation = calculateStandardDeviation(values); - - // ignore if mean or standard deviation are not numbers - if (Double.isNaN(alteredMean) || Double.isNaN(alteredStandardDeviation)) { - continue; - } - - groupedValues.add(values); - groupStatistics.setName(group.getKey()); - groupStatistics.setMeanExpression(BigDecimal.valueOf(alteredMean)); - groupStatistics.setStandardDeviation(BigDecimal.valueOf(alteredStandardDeviation)); - groupsStatistics.add(groupStatistics); - } - - // calculate p-value and add enrichment if atleast 2 groups have data - if (groupsStatistics.size() > 1) { - double pValue = calculatePValue(groupedValues); - if (Double.isNaN(pValue)) { - continue; - } - S expressionEnrichment = null; - if (ma instanceof GenericAssayMolecularAlteration) { - GenericAssayEnrichment genericAssayEnrichment = new GenericAssayEnrichment(); - genericAssayEnrichment.setStableId(ma.getStableId()); - expressionEnrichment = (S) genericAssayEnrichment; - } else { - GenomicEnrichment genomicEnrichment = new GenomicEnrichment(); - genomicEnrichment.setEntrezGeneId(Integer.valueOf(ma.getStableId())); - expressionEnrichment = (S) genomicEnrichment; - } - expressionEnrichment.setpValue(BigDecimal.valueOf(pValue)); - expressionEnrichment.setGroupsStatistics(groupsStatistics); - expressionEnrichments.add(expressionEnrichment); - } - } - return expressionEnrichments; - } - - private double[] getAlterationValues(List molecularDataValues, String molecularProfileId) { - - if (molecularProfileId.contains(RNA_SEQ)) { - return molecularDataValues.stream().mapToDouble(d -> { - double datum = Double.parseDouble(d); - // reset to 0 if there are any negative values and then do log1p - return Math.log1p(datum < 0 ? 0 : datum) / LOG2; - }).toArray(); - } else { - return molecularDataValues.stream().mapToDouble(g -> Double.parseDouble(g)).toArray(); - } - } - - private double calculatePValue(List alteredValues) { - - if (alteredValues.size() == 2) { - return TestUtils.tTest(alteredValues.get(0), alteredValues.get(1)); - } else { - // calculate Anova statisitcs if there are more than 2 groups - OneWayAnova oneWayAnova = new OneWayAnova(); - return oneWayAnova.anovaPValue(alteredValues); - } - } - - private double calculateStandardDeviation(double[] values) { - - DescriptiveStatistics descriptiveStatistics = new DescriptiveStatistics(); - for (double value : values) { - descriptiveStatistics.addValue(value); - } - return descriptiveStatistics.getStandardDeviation(); - } - - /** - * - * This method maps valid samples in molecularProfileCaseSets to indices in - * genetic_alteration.VALUES column. Recall this column of the - * genetic_alteration table is a comma separated list of scalar values. Each - * value in this list is associated with a sample at the same position found in - * the genetic_profile_samples.ORDERED_SAMPLE_LIST column. - * - * @param molecularProfileCaseSets - * @param enrichmentType - * @param molecularProfile - * @return - */ - private Map> getGroupIndicesMap( - Map> molecularProfileCaseSets, EnrichmentType enrichmentType, - MolecularProfile molecularProfile) { - - MolecularProfileSamples commaSeparatedSampleIdsOfMolecularProfile = molecularDataRepository - .getCommaSeparatedSampleIdsOfMolecularProfile(molecularProfile.getStableId()); - - List internalSampleIds = Arrays.stream(commaSeparatedSampleIdsOfMolecularProfile.getSplitSampleIds()) - .mapToInt(Integer::parseInt).boxed().collect(Collectors.toList()); - - Map internalSampleIdToIndexMap = IntStream.range(0, internalSampleIds.size()).boxed() - .collect(Collectors.toMap(internalSampleIds::get, Function.identity())); - - Map> selectedCaseIdToInternalIdsMap = getCaseIdToInternalIdsMap(molecularProfileCaseSets, - enrichmentType, molecularProfile); - - // this block map caseIds(sampleIds or patientids) to sampleIndices which - // represents the position fount in the - // genetic_profile_samples.ORDERED_SAMPLE_LIST column - Map> groupIndicesMap = molecularProfileCaseSets.entrySet().stream() - .collect(Collectors.toMap(entity -> entity.getKey(), entity -> { - List sampleIndices = new ArrayList<>(); - entity.getValue().forEach(molecularProfileCaseIdentifier -> { - // consider only valid samples - if (selectedCaseIdToInternalIdsMap.containsKey(molecularProfileCaseIdentifier.getCaseId())) { - List sampleInternalIds = selectedCaseIdToInternalIdsMap - .get(molecularProfileCaseIdentifier.getCaseId()); - - // only consider samples which are profiled for the give molecular profile id - sampleInternalIds.forEach(sampleInternalId -> { - if (internalSampleIdToIndexMap.containsKey(sampleInternalId)) { - sampleIndices.add(internalSampleIdToIndexMap.get(sampleInternalId)); - } - }); - } - }); - return sampleIndices; - })); - return groupIndicesMap; - } - - private Map> getCaseIdToInternalIdsMap( - Map> molecularProfileCaseSets, EnrichmentType enrichmentType, - MolecularProfile molecularProfile) { - - if (enrichmentType.equals(EnrichmentType.PATIENT)) { - List patientIds = molecularProfileCaseSets.values().stream() - .flatMap(molecularProfileCaseSet -> molecularProfileCaseSet.stream() - .map(MolecularProfileCaseIdentifier::getCaseId)) - .collect(Collectors.toList()); - - List samples = sampleService - .getAllSamplesOfPatientsInStudy(molecularProfile.getCancerStudyIdentifier(), patientIds, "SUMMARY"); - - return samples.stream().collect(Collectors.groupingBy(Sample::getPatientStableId, - Collectors.mapping(Sample::getInternalId, Collectors.toList()))); - } else { - List sampleIds = new ArrayList<>(); - List studyIds = new ArrayList<>(); - - molecularProfileCaseSets.values().forEach(molecularProfileCaseIdentifiers -> { - molecularProfileCaseIdentifiers.forEach(molecularProfileCaseIdentifier -> { - sampleIds.add(molecularProfileCaseIdentifier.getCaseId()); - studyIds.add(molecularProfile.getCancerStudyIdentifier()); - }); - }); - List samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); - - return samples.stream() - .collect(Collectors.toMap(Sample::getStableId, x -> Arrays.asList(x.getInternalId()))); - } - } -} + @Autowired + private SampleService sampleService; + @Autowired + private MolecularDataRepository molecularDataRepository; + + private static final double LOG2 = Math.log(2); + private static final String RNA_SEQ = "rna_seq"; + private static final List posTypeList = Arrays.asList("true", "yes"); + private static final List negTypeList = Arrays.asList("false", "no"); + private static final String ALTERED = "1"; + private static final String UNALTERED = "0"; + public List getEnrichments( + MolecularProfile molecularProfile, + Map> molecularProfileCaseSets, EnrichmentType enrichmentType, + Iterable maItr) { + List expressionEnrichments = new ArrayList<>(); + + Map> groupIndicesMap = getGroupIndicesMap(molecularProfileCaseSets, enrichmentType, + molecularProfile); + for (MolecularAlteration ma : maItr) { + List groupsStatistics = new ArrayList(); + // used for p-value calculation + List groupedValues = new ArrayList(); + + for (Entry> group : groupIndicesMap.entrySet()) { + + // get expression values to all the indices in the group + List molecularDataValues = group.getValue().stream() + .map(sampleIndex -> ma.getSplitValues()[sampleIndex]) + .filter(a -> NumberUtils.isNumber(a)) + .collect(Collectors.toList()); + + // ignore group if there are less than 2 values + if (molecularDataValues.size() < 2) { + continue; + } + + double[] values = getAlterationValues(molecularDataValues, molecularProfile.getStableId()); + + GroupStatistics groupStatistics = new GroupStatistics(); + double alteredMean = StatUtils.mean(values); + double alteredStandardDeviation = calculateStandardDeviation(values); + + // ignore if mean or standard deviation are not numbers + if (Double.isNaN(alteredMean) || Double.isNaN(alteredStandardDeviation)) { + continue; + } + + groupedValues.add(values); + groupStatistics.setName(group.getKey()); + groupStatistics.setMeanExpression(BigDecimal.valueOf(alteredMean)); + groupStatistics.setStandardDeviation(BigDecimal.valueOf(alteredStandardDeviation)); + groupsStatistics.add(groupStatistics); + } + + // calculate p-value and add enrichment if atleast 2 groups have data + if (groupsStatistics.size() > 1) { + double pValue = calculatePValue(groupedValues); + if (Double.isNaN(pValue)) { + continue; + } + S expressionEnrichment = null; + if (ma instanceof GenericAssayMolecularAlteration) { + GenericAssayEnrichment genericAssayEnrichment = new GenericAssayEnrichment(); + genericAssayEnrichment.setStableId(ma.getStableId()); + expressionEnrichment = (S) genericAssayEnrichment; + } else { + GenomicEnrichment genomicEnrichment = new GenomicEnrichment(); + genomicEnrichment.setEntrezGeneId(Integer.valueOf(ma.getStableId())); + expressionEnrichment = (S) genomicEnrichment; + } + expressionEnrichment.setpValue(BigDecimal.valueOf(pValue)); + expressionEnrichment.setGroupsStatistics(groupsStatistics); + expressionEnrichments.add(expressionEnrichment); + } + } + return expressionEnrichments; + } + + public List getGenericAssayCategoricalEnrichments( + MolecularProfile molecularProfile, + Map> molecularProfileCaseSets, EnrichmentType enrichmentType, + Iterable maItr) { + + List expressionEnrichments = new ArrayList<>(); + Map> groupCategoryStatistics = new HashMap<>(); + Map> groupIndicesMap = getGroupIndicesMap(molecularProfileCaseSets, enrichmentType, + molecularProfile); + + for (MolecularAlteration ma : maItr) { + List groupsStatistics = new ArrayList(); + for (Entry> group : groupIndicesMap.entrySet()) { + // Get the corresponding split values for the group + List groupValues = group.getValue().stream() + .map(sampleIndex -> ma.getSplitValues()[sampleIndex]) + .collect(Collectors.toList()); + // Group and count the split values + Map groupedSplitValues = groupValues.stream() + .collect(Collectors.toMap(Function.identity(), v -> 1, Integer::sum)); + + // ignore group if there are less than 2 values + if (groupValues.size() < 2) { + continue; + } + + GroupStatistics groupStatistics = new GroupStatistics(); + groupStatistics.setName(group.getKey()); + groupsStatistics.add(groupStatistics); + groupCategoryStatistics.put(group.getKey(), groupedSplitValues); + } + + // calculate p-value and add enrichment if atleast 2 groups have data + + if (groupsStatistics.size() > 1) { + long[][] array = getCategoricalValues(groupCategoryStatistics); + double pValue; + if(array[0].length <= 1) { + pValue = 1; + } else { + ChiSquareTest chiSquareTest = new ChiSquareTest(); + pValue = chiSquareTest.chiSquareTest(array); + } + + // set p-value to 1 when the cases in all groups are altered + if (Double.isNaN(pValue)) { + pValue = 1; + } + + S expressionEnrichment = null; + GenericAssayCategoricalEnrichment genericAssayCategoricalEnrichment = new GenericAssayCategoricalEnrichment(); + genericAssayCategoricalEnrichment.setStableId(ma.getStableId()); + expressionEnrichment = (S) genericAssayCategoricalEnrichment; + + expressionEnrichment.setpValue(BigDecimal.valueOf(pValue)); + expressionEnrichment.setGroupsStatistics(groupsStatistics); + expressionEnrichments.add(expressionEnrichment); + } + } + return expressionEnrichments; + } + + public List getGenericAssayBinaryEnrichments( + MolecularProfile molecularProfile, + Map> molecularProfileCaseSets, EnrichmentType enrichmentType, + Iterable maItr) { + List expressionEnrichments = new ArrayList<>(); + + Map> groupIndicesMap = getGroupIndicesMap(molecularProfileCaseSets, enrichmentType, + molecularProfile); + + for (MolecularAlteration ma : maItr) { + List genericAssayCountSummaries = new ArrayList<>(); + List groupsStatistics = new ArrayList(); + // used for p-value calculation + List groupedValues = new ArrayList(); + + for (Entry> group : groupIndicesMap.entrySet()) { + GenericAssayCountSummary genericAssayCountSummary = new GenericAssayCountSummary(); + genericAssayCountSummary.setName(group.getKey()); + + // get expression values to all the indices in the group, filter NA and map binary values + List molecularDataValues = group.getValue().stream() + .map(sampleIndex -> ma.getSplitValues()[sampleIndex]) + .filter(StringUtils::isNotEmpty) + .map(a ->{ + if (posTypeList.contains(a)) { + return ALTERED; + } else if (negTypeList.contains(a)) { + return UNALTERED; + } else { + return a; + } + }) + .collect(Collectors.toList()); + + // ignore group if there are less than 2 values + if (molecularDataValues.size() < 2) { + continue; + } + genericAssayCountSummary.setTotalCount(molecularDataValues.size()); + + double[] values = getAlterationValues(molecularDataValues, molecularProfile.getStableId()); + genericAssayCountSummary.setCount((int) Arrays.stream(values) + .filter(num -> num == 1) + .count()); + GroupStatistics groupStatistics = new GroupStatistics(); + double alteredMean = StatUtils.mean(values); + double alteredStandardDeviation = calculateStandardDeviation(values); + + // ignore if mean or standard deviation are not numbers + if (Double.isNaN(alteredMean) || Double.isNaN(alteredStandardDeviation)) { + continue; + } + + groupedValues.add(values); + groupStatistics.setName(group.getKey()); + groupStatistics.setMeanExpression(BigDecimal.valueOf(alteredMean)); + groupStatistics.setStandardDeviation(BigDecimal.valueOf(alteredStandardDeviation)); + groupsStatistics.add(groupStatistics); + genericAssayCountSummaries.add(genericAssayCountSummary); + } + + // calculate p-value and add enrichment if atleast 2 groups have data + if (groupsStatistics.size() > 1) { + + double pValue = calculatePValue(groupedValues); + if (Double.isNaN(pValue)) { + continue; + } + S expressionEnrichment = null; + GenericAssayBinaryEnrichment genericAssayBinaryEnrichment = new GenericAssayBinaryEnrichment(); + genericAssayBinaryEnrichment.setStableId(ma.getStableId()); + genericAssayBinaryEnrichment.setCounts(genericAssayCountSummaries); + expressionEnrichment = (S) genericAssayBinaryEnrichment; + + expressionEnrichment.setpValue(BigDecimal.valueOf(pValue)); + expressionEnrichment.setGroupsStatistics(groupsStatistics); + expressionEnrichments.add(expressionEnrichment); + } + } + return expressionEnrichments; + } + + private double[] getAlterationValues(List molecularDataValues, String molecularProfileId) { + + if (molecularProfileId.contains(RNA_SEQ)) { + return molecularDataValues.stream().mapToDouble(d -> { + double datum = Double.parseDouble(d); + // reset to 0 if there are any negative values and then do log1p + return Math.log1p(datum < 0 ? 0 : datum) / LOG2; + }).toArray(); + } else { + return molecularDataValues.stream().mapToDouble(g -> Double.parseDouble(g)).toArray(); + } + } + + private long[][] getCategoricalValues(Map> groupCategoryStatistics) { + // Determine the number of rows and columns + int numRows = groupCategoryStatistics.size(); + Set allCategories = groupCategoryStatistics.values().stream() + .flatMap(innerMap -> innerMap.keySet().stream()) + .collect(Collectors.toSet()); + int numCols = allCategories.size(); + + // Create the 2-dimensional long array + long[][] array = new long[numRows][numCols]; + + // Iterate over the outer map (group -> categories) + List groupKeys = new ArrayList<>(groupCategoryStatistics.keySet()); + for (int row = 0; row < numRows; row++) { + String groupKey = groupKeys.get(row); + Map innerMap = groupCategoryStatistics.get(groupKey); + + // Iterate over all categories + List categoryKeys = new ArrayList<>(allCategories); + for (int col = 0; col < numCols; col++) { + String categoryKey = categoryKeys.get(col); + + // Get the count from the inner map, or set as zero if the category doesn't exist + int count = innerMap.getOrDefault(categoryKey, 0); + array[row][col] = count; + } + } + return array; + } + + private double calculatePValue(List alteredValues) { + + if (alteredValues.size() == 2) { + return TestUtils.tTest(alteredValues.get(0), alteredValues.get(1)); + } else { + // calculate Anova statisitcs if there are more than 2 groups + OneWayAnova oneWayAnova = new OneWayAnova(); + return oneWayAnova.anovaPValue(alteredValues); + } + } + + private double calculateStandardDeviation(double[] values) { + + DescriptiveStatistics descriptiveStatistics = new DescriptiveStatistics(); + for (double value : values) { + descriptiveStatistics.addValue(value); + } + return descriptiveStatistics.getStandardDeviation(); + } + + /** + * + * This method maps valid samples in molecularProfileCaseSets to indices in + * genetic_alteration.VALUES column. Recall this column of the + * genetic_alteration table is a comma separated list of scalar values. Each + * value in this list is associated with a sample at the same position found in + * the genetic_profile_samples.ORDERED_SAMPLE_LIST column. + * + * @param molecularProfileCaseSets + * @param enrichmentType + * @param molecularProfile + * @return + */ + private Map> getGroupIndicesMap( + Map> molecularProfileCaseSets, EnrichmentType enrichmentType, + MolecularProfile molecularProfile) { + + MolecularProfileSamples commaSeparatedSampleIdsOfMolecularProfile = molecularDataRepository + .getCommaSeparatedSampleIdsOfMolecularProfile(molecularProfile.getStableId()); + + List internalSampleIds = Arrays.stream(commaSeparatedSampleIdsOfMolecularProfile.getSplitSampleIds()) + .mapToInt(Integer::parseInt).boxed().collect(Collectors.toList()); + + Map internalSampleIdToIndexMap = IntStream.range(0, internalSampleIds.size()).boxed() + .collect(Collectors.toMap(internalSampleIds::get, Function.identity())); + + Map> selectedCaseIdToInternalIdsMap = getCaseIdToInternalIdsMap(molecularProfileCaseSets, + enrichmentType, molecularProfile); + + // this block map caseIds(sampleIds or patientids) to sampleIndices which + // represents the position fount in the + // genetic_profile_samples.ORDERED_SAMPLE_LIST column + Map> groupIndicesMap = molecularProfileCaseSets.entrySet().stream() + .collect(Collectors.toMap(entity -> entity.getKey(), entity -> { + List sampleIndices = new ArrayList<>(); + entity.getValue().forEach(molecularProfileCaseIdentifier -> { + // consider only valid samples + if (selectedCaseIdToInternalIdsMap.containsKey(molecularProfileCaseIdentifier.getCaseId())) { + List sampleInternalIds = selectedCaseIdToInternalIdsMap + .get(molecularProfileCaseIdentifier.getCaseId()); + + // only consider samples which are profiled for the give molecular profile id + sampleInternalIds.forEach(sampleInternalId -> { + if (internalSampleIdToIndexMap.containsKey(sampleInternalId)) { + sampleIndices.add(internalSampleIdToIndexMap.get(sampleInternalId)); + } + }); + } + }); + return sampleIndices; + })); + return groupIndicesMap; + } + + private Map> getCaseIdToInternalIdsMap( + Map> molecularProfileCaseSets, EnrichmentType enrichmentType, + MolecularProfile molecularProfile) { + + if (enrichmentType.equals(EnrichmentType.PATIENT)) { + List patientIds = molecularProfileCaseSets.values().stream() + .flatMap(molecularProfileCaseSet -> molecularProfileCaseSet.stream() + .map(MolecularProfileCaseIdentifier::getCaseId)) + .collect(Collectors.toList()); + + List samples = sampleService + .getAllSamplesOfPatientsInStudy(molecularProfile.getCancerStudyIdentifier(), patientIds, "SUMMARY"); + + return samples.stream().collect(Collectors.groupingBy(Sample::getPatientStableId, + Collectors.mapping(Sample::getInternalId, Collectors.toList()))); + } else { + List sampleIds = new ArrayList<>(); + List studyIds = new ArrayList<>(); + + molecularProfileCaseSets.values().forEach(molecularProfileCaseIdentifiers -> { + molecularProfileCaseIdentifiers.forEach(molecularProfileCaseIdentifier -> { + sampleIds.add(molecularProfileCaseIdentifier.getCaseId()); + studyIds.add(molecularProfile.getCancerStudyIdentifier()); + }); + }); + List samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); + + return samples.stream() + .collect(Collectors.toMap(Sample::getStableId, x -> Arrays.asList(x.getInternalId()))); + } + } + +} \ No newline at end of file diff --git a/service/src/main/java/org/cbioportal/service/util/FisherExactTestCalculator.java b/service/src/main/java/org/cbioportal/service/util/FisherExactTestCalculator.java index b6f4bbf6eab..150fb370178 100644 --- a/service/src/main/java/org/cbioportal/service/util/FisherExactTestCalculator.java +++ b/service/src/main/java/org/cbioportal/service/util/FisherExactTestCalculator.java @@ -2,6 +2,8 @@ import org.springframework.stereotype.Component; +import java.math.BigDecimal; + @Component public class FisherExactTestCalculator { @@ -40,4 +42,83 @@ public double getCumulativePValue(int a, int b, int c, int d) { } return p; } + + public double getTwoTailedPValue(int a, int b, int c, int d) { + + int min, i; + int n = a + b + c + d; + double p = 0; + double[] f = new double[n + 1]; + f[0] = 0.0; + + for (int j = 1; j <= n; j++) { + f[j] = f[j - 1] + Math.log(j); + } + + double baseP = getPValue(a, b, c, d, f); +// in order for a table under consideration to have its p-value included +// in the final result, it must have a p-value less than the baseP, i.e. +// Fisher's exact test computes the probability, given the observed marginal +// frequencies, of obtaining exactly the frequencies observed and any configuration more extreme. +// By "more extreme," we mean any configuration (given observed marginals) with a smaller probability of +// occurrence in the same direction (one-tailed) or in both directions (two-tailed). + + int initialA = a, initialB = b, initialC = c, initialD = d; + p += baseP; + + min = (c < b) ? c : b; + for (i = 0; i < min; i++) { + double tempP = getPValue(++a, --b, --c, ++d, f); + if (tempP <= baseP) { + p += tempP; + } + } + + // reset the values to their original so we can repeat this process for the other side + a = initialA; + b = initialB; + c = initialC; + d = initialD; + + min = (a < d) ? a : d; + for (i = 0; i < min; i++) { + double pTemp = getPValue(--a, ++b, ++c, --d, f); + if (pTemp <= baseP) { + p += pTemp; + } + } + return p; + } + public BigDecimal[] calcqValue(BigDecimal[] pValuesInIncreasingOrder) { + BigDecimal cachedElement = BigDecimal.valueOf(0.0); + int dataLength = pValuesInIncreasingOrder.length; + BigDecimal[] reversedQValues = new BigDecimal[dataLength]; + + reverseValues(dataLength, pValuesInIncreasingOrder); + + for (int i = 0; i < dataLength; i++) { + if (i > 0) { + BigDecimal calculatedValue = cachedElement.min( + (pValuesInIncreasingOrder[i].multiply(new BigDecimal(dataLength))).divide(new BigDecimal(dataLength - i), BigDecimal.ROUND_HALF_UP) + ); + cachedElement = calculatedValue; + reversedQValues[i] = calculatedValue; + } else { + cachedElement = pValuesInIncreasingOrder[i]; + reversedQValues[i] = pValuesInIncreasingOrder[i]; + } + } + + reverseValues(dataLength, reversedQValues); + + return reversedQValues; + } + + private void reverseValues(int dataLength, BigDecimal[] reversedQValues) { + for (int i = 0; i < dataLength / 2; i++) { + BigDecimal temp = reversedQValues[i]; + reversedQValues[i] = reversedQValues[dataLength - i - 1]; + reversedQValues[dataLength - i - 1] = temp; + } + } } diff --git a/service/src/main/java/org/cbioportal/service/util/ProfiledCasesCounter.java b/service/src/main/java/org/cbioportal/service/util/ProfiledCasesCounter.java index c59aa9b8ea0..3a4b3641df1 100644 --- a/service/src/main/java/org/cbioportal/service/util/ProfiledCasesCounter.java +++ b/service/src/main/java/org/cbioportal/service/util/ProfiledCasesCounter.java @@ -11,7 +11,7 @@ import org.springframework.stereotype.Component; @Component -public class ProfiledCasesCounter { +public class ProfiledCasesCounter { @Autowired private GenePanelService genePanelService; @@ -27,6 +27,7 @@ public void calculate(List alterationCounts, List genePanelDataList, boolean includeMissingAlterationsFromGenePanel, Function caseUniqueIdentifier) { + ProfiledCaseType profiledCaseType = (caseUniqueIdentifier == patientUniqueIdentifier) ? ProfiledCaseType.PATIENT : ProfiledCaseType.SAMPLE; Map> casesWithDataInGenePanel = extractCasesWithDataInGenePanel(genePanelDataList, caseUniqueIdentifier); @@ -35,26 +36,30 @@ public void calculate(List alterationCounts, genePanels = genePanelService.fetchGenePanels(new ArrayList<>(casesWithDataInGenePanel.keySet()), "DETAILED"); } - Map, List> geneGenePanelMap = new HashMap<>(); + Map, List> geneToGenePanel = new HashMap<>(); for (GenePanel genePanel : genePanels) { for (GenePanelToGene genePanelToGene : genePanel.getGenes()) { + // TODO I am not sure whether it is smart to include the HUGO gene suymbol in the key here. + // What if two panels have the same Entrez gene id with different Hugo gene symbols? If that situation + // can never occur, better not include the HUGO symbol in the key and only use entrez gene id. It confuses + // developers that may think it is an important key element. Pair key = new Pair<>(genePanelToGene.getEntrezGeneId(), genePanelToGene.getHugoGeneSymbol()); - if (geneGenePanelMap.containsKey(key)) { - geneGenePanelMap.get(key).add(genePanel); + if (geneToGenePanel.containsKey(key)) { + geneToGenePanel.get(key).add(genePanel); } else { List geneGenePanelList = new ArrayList<>(); geneGenePanelList.add(genePanel); - geneGenePanelMap.put(key, geneGenePanelList); + geneToGenePanel.put(key, geneGenePanelList); } } } - List profiled = genePanelDataList + List genePanelData = genePanelDataList .stream() .filter(GenePanelData::getProfiled) .collect(Collectors.toList()); - Set profiledCases = profiled + Set profiledCases = genePanelData .stream() // there can be duplicate patient or sample id, append study id .map(caseUniqueIdentifier) @@ -66,7 +71,7 @@ public void calculate(List alterationCounts, // so a case is considered without panel data only if none of the profiles has a gene panel id // first identify cases with gene panel data - Set casesWithPanelData = profiled + Set casesWithPanelData = genePanelData .stream() .filter(g -> g.getGenePanelId() != null) // there can be duplicate patient or sample id, append study id @@ -74,7 +79,7 @@ public void calculate(List alterationCounts, .collect(Collectors.toSet()); // find all unique cases - Set casesWithoutPanelData = profiled + Set casesWithoutPanelData = genePanelData .stream() // there can be duplicate patient or sample id, append study id .map(caseUniqueIdentifier) @@ -83,17 +88,15 @@ public void calculate(List alterationCounts, // removing cases with panel data from all unique cases gives us the cases without panel data casesWithoutPanelData.removeAll(casesWithPanelData); - for (AlterationCountByGene alterationCountByGene : alterationCounts) { - Integer entrezGeneId = alterationCountByGene.getEntrezGeneId(); - Set totalProfiledPatients = new HashSet(); + for (T alterationCount : alterationCounts) { + Set totalProfiledPatients = new HashSet<>(); + Set allMatchingGenePanelIds = new HashSet<>(); int totalProfiledSamples = 0; - Set allMatchingGenePanelIds = new HashSet(); - Pair key = new Pair<>(entrezGeneId,alterationCountByGene.getHugoGeneSymbol()); // different calculations depending on if gene is linked to gene panels - if (geneGenePanelMap.containsKey(key)) { + if (alterationIsCoveredByGenePanel(alterationCount, geneToGenePanel)) { // for every gene panel associated containing the gene, use the sum of unique cases // as well as cases without panel data - for (GenePanel genePanel : geneGenePanelMap.get(key)) { + for (GenePanel genePanel : getGenePanelsForAlterationCount(alterationCount, geneToGenePanel)) { allMatchingGenePanelIds.add(genePanel.getStableId()); if (profiledCaseType == ProfiledCaseType.PATIENT) { totalProfiledPatients.addAll(casesWithDataInGenePanel.get(genePanel.getStableId())); @@ -103,37 +106,37 @@ public void calculate(List alterationCounts, } if (profiledCaseType == ProfiledCaseType.PATIENT) { totalProfiledPatients.addAll(casesWithoutPanelData); - alterationCountByGene.setNumberOfProfiledCases(totalProfiledPatients.size()); + alterationCount.setNumberOfProfiledCases(totalProfiledPatients.size()); } else { totalProfiledSamples += casesWithoutPanelData.size(); - alterationCountByGene.setNumberOfProfiledCases(totalProfiledSamples); + alterationCount.setNumberOfProfiledCases(totalProfiledSamples); } } else { // we use profiledCasesCount instead of casesWithoutPanelData to // prevent a divide by zero error which can happen for targeted studies // in which certain genes have events that are not captured by the panel. - alterationCountByGene.setNumberOfProfiledCases(profiledCasesCount); + alterationCount.setNumberOfProfiledCases(profiledCasesCount); } - alterationCountByGene.setMatchingGenePanelIds(allMatchingGenePanelIds); + alterationCount.setMatchingGenePanelIds(allMatchingGenePanelIds); } if (includeMissingAlterationsFromGenePanel) { - Map genesWithAlteration = alterationCounts.stream() - .collect(Collectors.toMap(AlterationCountByGene::getEntrezGeneId, x -> true)); + Set genesWithAlteration = alterationCounts.stream() + .flatMap(count -> Arrays.stream(count.getEntrezGeneIds())) + .collect(Collectors.toSet()); - geneGenePanelMap.entrySet().forEach(entry -> { - Pair key = entry.getKey(); - Integer entrezGeneId = key.getFirst(); - String hugoGeneSymbol = key.getSecond(); + geneToGenePanel.entrySet().forEach(entry -> { + Integer entrezGeneId = entry.getKey().getFirst(); + String hugoGeneSymbol = entry.getKey().getSecond(); // add alterationCount object where there are no alterations but have genePanel // object - if (!genesWithAlteration.containsKey(entrezGeneId)) { + if (!genesWithAlteration.contains(entrezGeneId)) { AlterationCountByGene alterationCountByGene = new AlterationCountByGene(); - Set totalProfiledPatients = new HashSet(); + Set totalProfiledPatients = new HashSet<>(); + Set allMatchingGenePanelIds = new HashSet<>(); int totalProfiledSamples = 0; - Set allMatchingGenePanelIds = new HashSet(); - for (GenePanel genePanel : geneGenePanelMap.get(key)) { + for (GenePanel genePanel : geneToGenePanel.get(new Pair<>(entrezGeneId, hugoGeneSymbol))) { allMatchingGenePanelIds.add(genePanel.getStableId()); if (profiledCaseType == ProfiledCaseType.PATIENT) { totalProfiledPatients.addAll(casesWithDataInGenePanel.get(genePanel.getStableId())); @@ -168,16 +171,39 @@ private Map> extractCasesWithDataInGenePanel( List genePanelDataList, Function caseUniqueIdentifier) { - Map> casesWithDataInGenePanel = new HashMap>(); + Map> casesWithDataInGenePanel = new HashMap<>(); // loop through all membership records -- ignore any where g.getGenePanelId == null for (GenePanelData genePanelDataRecord : genePanelDataList) { String associatedGenePanel = genePanelDataRecord.getGenePanelId(); if (associatedGenePanel != null) { - casesWithDataInGenePanel.putIfAbsent(associatedGenePanel, new HashSet()); + casesWithDataInGenePanel.putIfAbsent(associatedGenePanel, new HashSet<>()); Set casesForThisGenePanel = casesWithDataInGenePanel.get(associatedGenePanel); casesForThisGenePanel.add(caseUniqueIdentifier.apply(genePanelDataRecord)); } } return casesWithDataInGenePanel; } + + private boolean alterationIsCoveredByGenePanel(T alterationCount, Map, List> entrezIdToGenePanel) { + return !getGenePanelsForAlterationCount(alterationCount, entrezIdToGenePanel).isEmpty(); + } + + private List getGenePanelsForAlterationCount(T alterationCount, Map, List> entrezIdToGenePanel) { + if (alterationCount instanceof AlterationCountByGene) { + Integer entrezId = ((AlterationCountByGene) alterationCount).getEntrezGeneId(); + String hugoSymbol = ((AlterationCountByGene) alterationCount).getHugoGeneSymbol(); + return entrezIdToGenePanel.getOrDefault(new Pair<>(entrezId, hugoSymbol), new ArrayList<>()); + } + if (alterationCount instanceof AlterationCountByStructuralVariant) { + Integer gene1EntrezId = ((AlterationCountByStructuralVariant) alterationCount).getGene1EntrezGeneId(); + String gene1HugoSymbol = ((AlterationCountByStructuralVariant) alterationCount).getGene1HugoGeneSymbol(); + Integer gene2EntrezId = ((AlterationCountByStructuralVariant) alterationCount).getGene2EntrezGeneId(); + String gene2HugoSymbol = ((AlterationCountByStructuralVariant) alterationCount).getGene2HugoGeneSymbol(); + List panels = entrezIdToGenePanel.getOrDefault(new Pair<>(gene1EntrezId, gene2HugoSymbol), new ArrayList<>()); + panels.addAll(entrezIdToGenePanel.getOrDefault(new Pair<>(gene2EntrezId, gene2HugoSymbol), new ArrayList<>())); + return panels.stream().distinct().collect(Collectors.toList()); + } + throw new IllegalArgumentException("At present only AlterationCountByGene or AlterationCountByStructuralVariant are " + + "supported."); + } } diff --git a/service/src/main/java/org/cbioportal/service/util/SessionServiceConfig.java b/service/src/main/java/org/cbioportal/service/util/SessionServiceConfig.java new file mode 100644 index 00000000000..ff0adc546ef --- /dev/null +++ b/service/src/main/java/org/cbioportal/service/util/SessionServiceConfig.java @@ -0,0 +1,16 @@ +package org.cbioportal.service.util; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SessionServiceConfig { + + @Bean + public ObjectMapper sessionServiceObjectMapper() { + return new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + +} \ No newline at end of file diff --git a/web/src/main/java/org/cbioportal/web/util/SessionServiceRequestHandler.java b/service/src/main/java/org/cbioportal/service/util/SessionServiceRequestHandler.java similarity index 57% rename from web/src/main/java/org/cbioportal/web/util/SessionServiceRequestHandler.java rename to service/src/main/java/org/cbioportal/service/util/SessionServiceRequestHandler.java index 8985c316ca9..cabe6cfa934 100644 --- a/web/src/main/java/org/cbioportal/web/util/SessionServiceRequestHandler.java +++ b/service/src/main/java/org/cbioportal/service/util/SessionServiceRequestHandler.java @@ -1,15 +1,10 @@ -package org.cbioportal.web.util; +package org.cbioportal.service.util; import java.nio.charset.Charset; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.StringUtils; -import org.cbioportal.session_service.domain.Session; import org.cbioportal.session_service.domain.SessionType; -import org.cbioportal.web.parameter.CustomDataSession; -import org.cbioportal.web.parameter.CustomGeneList; -import org.cbioportal.web.parameter.PageSettings; -import org.cbioportal.web.parameter.VirtualStudy; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -18,9 +13,6 @@ import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; - @Component public class SessionServiceRequestHandler { @@ -56,32 +48,16 @@ public HttpHeaders getHttpHeaders() { }; } - public Session getSession(SessionType type, String id) throws Exception { + public String getSessionDataJson(SessionType type, String id) throws Exception { RestTemplate restTemplate = new RestTemplate(); // add basic authentication in header - HttpEntity headers = new HttpEntity(getHttpHeaders()); + HttpEntity headers = new HttpEntity<>(getHttpHeaders()); ResponseEntity responseEntity = restTemplate.exchange(sessionServiceURL + type + "/" + id, HttpMethod.GET, headers, String.class); - ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - - Session session; - - if (type.equals(SessionType.virtual_study) || type.equals(SessionType.group)) { - session = mapper.readValue(responseEntity.getBody(), VirtualStudy.class); - } else if (type.equals(SessionType.settings)) { - session = mapper.readValue(responseEntity.getBody(), PageSettings.class); - } else if (type.equals(SessionType.custom_data)) { - session = mapper.readValue(responseEntity.getBody(), CustomDataSession.class); - } else if (type.equals(SessionType.custom_gene_list)) { - session = mapper.readValue(responseEntity.getBody(), CustomGeneList.class); - } else { - session = mapper.readValue(responseEntity.getBody(), Session.class); - } - - return session; + return responseEntity.getBody(); } } diff --git a/service/src/test/java/org/cbioportal/service/impl/AlterationCountServiceImplTest.java b/service/src/test/java/org/cbioportal/service/impl/AlterationCountServiceImplTest.java index 9a213c7efd9..bd2c4955826 100644 --- a/service/src/test/java/org/cbioportal/service/impl/AlterationCountServiceImplTest.java +++ b/service/src/test/java/org/cbioportal/service/impl/AlterationCountServiceImplTest.java @@ -2,7 +2,6 @@ import org.apache.commons.math3.util.Pair; import org.cbioportal.model.*; -import org.cbioportal.model.QueryElement; import org.cbioportal.model.util.Select; import org.cbioportal.persistence.AlterationRepository; import org.cbioportal.persistence.MolecularProfileRepository; @@ -33,6 +32,8 @@ public class AlterationCountServiceImplTest extends BaseServiceImplTest { private AlterationEnrichmentUtil alterationEnrichmentUtil; @Mock private AlterationEnrichmentUtil alterationEnrichmentUtilCna; + @Mock + private AlterationEnrichmentUtil alterationEnrichmentUtilStructVar; @Spy @InjectMocks private MolecularProfileUtil molecularProfileUtil; @@ -47,6 +48,7 @@ public class AlterationCountServiceImplTest extends BaseServiceImplTest { boolean includeMissingAlterationsFromGenePanel = false; List expectedCountByGeneList; List expectedCnaCountByGeneList; + List expectedStructuralVariantList; AlterationFilter alterationFilter = new AlterationFilter( mutationEventTypes, cnaEventTypes, @@ -79,18 +81,26 @@ public void setup() { copyNumberCountByGene.setEntrezGeneId(ENTREZ_GENE_ID_1); copyNumberCountByGene.setAlteration(2); expectedCnaCountByGeneList = Arrays.asList(copyNumberCountByGene); + + final AlterationCountByStructuralVariant alterationCountByStructuralVariant = new AlterationCountByStructuralVariant(); + alterationCountByStructuralVariant.setGene1EntrezGeneId(ENTREZ_GENE_ID_1); + alterationCountByStructuralVariant.setGene2EntrezGeneId(ENTREZ_GENE_ID_2); + alterationCountByStructuralVariant.setGene1HugoGeneSymbol(HUGO_GENE_SYMBOL_1); + alterationCountByStructuralVariant.setGene2HugoGeneSymbol(HUGO_GENE_SYMBOL_2); + expectedStructuralVariantList = Arrays.asList(alterationCountByStructuralVariant); + } @Test - public void getSampleAlterationCounts() { + public void getSampleAlterationGeneCounts() { // this mock tests correct argument types - when(alterationRepository.getSampleAlterationCounts( + when(alterationRepository.getSampleAlterationGeneCounts( new HashSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)).thenReturn(expectedCountByGeneList); - Pair, Long> result = alterationCountService.getSampleAlterationCounts( + Pair, Long> result = alterationCountService.getSampleAlterationGeneCounts( caseIdentifiers, entrezGeneIds, includeFrequency, @@ -102,15 +112,15 @@ public void getSampleAlterationCounts() { } @Test - public void getPatientAlterationCounts() { + public void getPatientAlterationGeneCounts() { // this mock tests correct argument types - when(alterationRepository.getPatientAlterationCounts( - caseIdentifiers, + when(alterationRepository.getPatientAlterationGeneCounts( + new HashSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)).thenReturn(expectedCountByGeneList); - Pair, Long> result = alterationCountService.getPatientAlterationCounts( + Pair, Long> result = alterationCountService.getPatientAlterationGeneCounts( caseIdentifiers, entrezGeneIds, includeFrequency, @@ -122,14 +132,14 @@ public void getPatientAlterationCounts() { @Test - public void getSampleMutationCounts() { + public void getSampleMutationGeneCounts() { // this mock tests correct argument types - when(alterationRepository.getSampleAlterationCounts( + when(alterationRepository.getSampleAlterationGeneCounts( new HashSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)).thenReturn(expectedCountByGeneList); - Pair, Long> result = alterationCountService.getSampleMutationCounts( + Pair, Long> result = alterationCountService.getSampleMutationGeneCounts( caseIdentifiers, entrezGeneIds, includeFrequency, @@ -141,15 +151,15 @@ public void getSampleMutationCounts() { } @Test - public void getPatientMutationCounts() throws MolecularProfileNotFoundException { + public void getPatientMutationGeneCounts() throws MolecularProfileNotFoundException { // this mock tests correct argument types - when(alterationRepository.getPatientAlterationCounts( - caseIdentifiers, + when(alterationRepository.getPatientAlterationGeneCounts( + new HashSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)).thenReturn(expectedCountByGeneList); - Pair, Long> result = alterationCountService.getPatientMutationCounts( + Pair, Long> result = alterationCountService.getPatientMutationGeneCounts( caseIdentifiers, entrezGeneIds, includeFrequency, @@ -161,15 +171,15 @@ public void getPatientMutationCounts() throws MolecularProfileNotFoundException } @Test - public void getSampleCnaCounts() { + public void getSampleCnaGeneCounts() { // this mock tests correct argument types - when(alterationRepository.getSampleCnaCounts( + when(alterationRepository.getSampleCnaGeneCounts( new TreeSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)).thenReturn(expectedCnaCountByGeneList); - Pair, Long> result = alterationCountService.getSampleCnaCounts( + Pair, Long> result = alterationCountService.getSampleCnaGeneCounts( caseIdentifiers, entrezGeneIds, includeFrequency, @@ -182,16 +192,16 @@ public void getSampleCnaCounts() { } @Test - public void getPatientCnaCounts() { + public void getPatientCnaGeneCounts() { // this mock tests correct argument types - when(alterationRepository.getPatientCnaCounts( - caseIdentifiers, + when(alterationRepository.getPatientCnaGeneCounts( + new HashSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)).thenReturn(expectedCnaCountByGeneList); - Pair, Long> result = alterationCountService.getPatientCnaCounts( + Pair, Long> result = alterationCountService.getPatientCnaGeneCounts( caseIdentifiers, entrezGeneIds, includeFrequency, @@ -201,4 +211,22 @@ public void getPatientCnaCounts() { verify(alterationEnrichmentUtilCna, times(1)).includeFrequencyForPatients(anyList(), anyList(), anyBoolean()); Assert.assertEquals(expectedCnaCountByGeneList, result.getFirst()); } + + @Test + public void getSampleStructuralVariantCounts() { + + when(alterationRepository.getSampleStructuralVariantCounts( + new TreeSet<>(caseIdentifiers), + alterationFilter)).thenReturn(expectedStructuralVariantList); + + Pair, Long> result = alterationCountService.getSampleStructuralVariantCounts( + caseIdentifiers, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + + verify(alterationEnrichmentUtilStructVar, times(1)).includeFrequencyForSamples(anyList(), anyList(), anyBoolean()); + Assert.assertEquals(expectedStructuralVariantList, result.getFirst()); + + } } \ No newline at end of file diff --git a/service/src/test/java/org/cbioportal/service/impl/AlterationEnrichmentServiceImplTest.java b/service/src/test/java/org/cbioportal/service/impl/AlterationEnrichmentServiceImplTest.java index 45d8740e8ae..0c645bb2620 100644 --- a/service/src/test/java/org/cbioportal/service/impl/AlterationEnrichmentServiceImplTest.java +++ b/service/src/test/java/org/cbioportal/service/impl/AlterationEnrichmentServiceImplTest.java @@ -9,7 +9,6 @@ import org.cbioportal.model.MolecularProfileCaseIdentifier; import org.cbioportal.model.MutationCountByGene; import org.cbioportal.model.MutationEventType; -import org.cbioportal.model.QueryElement; import org.cbioportal.model.util.Select; import org.cbioportal.service.AlterationCountService; import org.cbioportal.service.util.AlterationEnrichmentUtil; @@ -71,7 +70,7 @@ public void getAlterationEnrichments() throws Exception { // return counts for each of the two groups for (String molecularProfileId : groupMolecularProfileCaseSets.keySet()) { - Mockito.when(alterationCountService.getSampleAlterationCounts( + Mockito.when(alterationCountService.getSampleAlterationGeneCounts( groupMolecularProfileCaseSets.get(molecularProfileId), Select.all(), true, true, alterationFilter) ).thenReturn(alterationSampleCountByGeneList); diff --git a/service/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java b/service/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java index 838c4c3a67b..827a7b752a5 100644 --- a/service/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java +++ b/service/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java @@ -59,5 +59,7 @@ public class BaseServiceImplTest { public static final String CATEGORY_VALUE_1 = "category_value1"; public static final String CATEGORY_VALUE_2 = "category_value2"; public static final String EMPTY_VALUE_1 = ""; - public static final String EMPTY_VALUE_2 = "NA"; + public static final String EMPTY_VALUE_2 = "NA"; + public static final String PROFILE_TYPE_1 = "profile_type1"; + public static final String PROFILE_TYPE_2 = "profile_type2"; } diff --git a/service/src/test/java/org/cbioportal/service/impl/ClinicalEventServiceImplTest.java b/service/src/test/java/org/cbioportal/service/impl/ClinicalEventServiceImplTest.java index 3353c099c14..89a0976c0dc 100644 --- a/service/src/test/java/org/cbioportal/service/impl/ClinicalEventServiceImplTest.java +++ b/service/src/test/java/org/cbioportal/service/impl/ClinicalEventServiceImplTest.java @@ -135,8 +135,8 @@ public void getMetaClinicalEvents() throws Exception { @Test public void getPatientsSamplesPerClinicalEventType() { - List studyIds = List.of(STUDY_ID); - List sampleIds = List.of(SAMPLE_ID1); + List studyIds = Arrays.asList(STUDY_ID); + List sampleIds = Arrays.asList(SAMPLE_ID1); Map> patientsSamplesPerEventType = new HashMap<>(); patientsSamplesPerEventType.put(CLINICAL_EVENT_TYPE, new HashSet<>(sampleIds)); @@ -150,8 +150,8 @@ public void getPatientsSamplesPerClinicalEventType() { @Test public void getClinicalEventTypeCounts() { - List studyIds = List.of(STUDY_ID); - List sampleIds = List.of(SAMPLE_ID1); + List studyIds = Arrays.asList(STUDY_ID); + List sampleIds = Arrays.asList(SAMPLE_ID1); Patient p = new Patient(); p.setCancerStudyIdentifier(STUDY_ID); @@ -161,9 +161,9 @@ public void getClinicalEventTypeCounts() { ce.setEventType(CLINICAL_EVENT_TYPE); Mockito.when(patientService.getPatientsOfSamples(anyList(), anyList())) - .thenReturn(List.of(p)); + .thenReturn(Arrays.asList(p)); Mockito.when(clinicalEventRepository.getPatientsDistinctClinicalEventInStudies(anyList(), anyList())) - .thenReturn(List.of(ce)); + .thenReturn(Arrays.asList(ce)); List eventTypeCounts = clinicalEventService.getClinicalEventTypeCounts(studyIds, sampleIds); Assert.assertEquals(1, eventTypeCounts.size()); diff --git a/service/src/test/java/org/cbioportal/service/impl/ExpressionEnrichmentServiceImplTest.java b/service/src/test/java/org/cbioportal/service/impl/ExpressionEnrichmentServiceImplTest.java index e4d1da579cf..a777176e26a 100644 --- a/service/src/test/java/org/cbioportal/service/impl/ExpressionEnrichmentServiceImplTest.java +++ b/service/src/test/java/org/cbioportal/service/impl/ExpressionEnrichmentServiceImplTest.java @@ -207,7 +207,7 @@ public void getGenomicEnrichments() throws Exception { } @Test - public void getGenericAssayEnrichments() throws Exception { + public void getGenericAssayNumericalEnrichments() throws Exception { geneMolecularProfile.setMolecularAlterationType(MolecularProfile.MolecularAlterationType.GENERIC_ASSAY); List molecularDataList = new ArrayList(); @@ -229,7 +229,7 @@ public void getGenericAssayEnrichments() throws Exception { .thenReturn(Arrays.asList(new GenericAssayMeta(HUGO_GENE_SYMBOL_1), new GenericAssayMeta(HUGO_GENE_SYMBOL_2))); - List result = enrichmentServiceImpl.getGenericAssayEnrichments(MOLECULAR_PROFILE_ID, + List result = enrichmentServiceImpl.getGenericAssayNumericalEnrichments(MOLECULAR_PROFILE_ID, molecularProfileCaseSets, EnrichmentType.SAMPLE); Assert.assertEquals(2, result.size()); @@ -301,7 +301,7 @@ public void getGenericAssayPatientLevelEnrichments() throws Exception { Mockito.when(sampleService.fetchSamples(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), Arrays.asList(SAMPLE_ID3, SAMPLE_ID4, SAMPLE_ID5, SAMPLE_ID1, SAMPLE_ID2), "ID")).thenReturn(samples); - List result = enrichmentServiceImpl.getGenericAssayEnrichments(MOLECULAR_PROFILE_ID, molecularProfilePatientLevelCaseSets, EnrichmentType.SAMPLE); + List result = enrichmentServiceImpl.getGenericAssayNumericalEnrichments(MOLECULAR_PROFILE_ID, molecularProfilePatientLevelCaseSets, EnrichmentType.SAMPLE); Assert.assertEquals(2, result.size()); GenericAssayEnrichment genericAssayEnrichment = result.get(0); diff --git a/service/src/test/java/org/cbioportal/service/impl/GenericAssayEnrichmentServiceImplTest.java b/service/src/test/java/org/cbioportal/service/impl/GenericAssayEnrichmentServiceImplTest.java new file mode 100644 index 00000000000..017a5ab005f --- /dev/null +++ b/service/src/test/java/org/cbioportal/service/impl/GenericAssayEnrichmentServiceImplTest.java @@ -0,0 +1,272 @@ +package org.cbioportal.service.impl; + +import org.cbioportal.model.meta.GenericAssayMeta; +import org.cbioportal.model.EnrichmentType; +import org.cbioportal.model.MolecularProfileCaseIdentifier; +import org.cbioportal.model.MolecularProfile; +import org.cbioportal.model.MolecularProfileSamples; +import org.cbioportal.model.CancerStudy; +import org.cbioportal.model.ReferenceGenome; +import org.cbioportal.model.Sample; +import org.cbioportal.model.GenericAssayMolecularAlteration; +import org.cbioportal.model.GenericAssayBinaryEnrichment; +import org.cbioportal.model.GenericAssayCategoricalEnrichment; +import org.cbioportal.model.GroupStatistics; + +import org.cbioportal.persistence.MolecularDataRepository; +import org.cbioportal.service.GenericAssayService; +import org.cbioportal.service.MolecularProfileService; +import org.cbioportal.service.SampleService; +import org.cbioportal.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.service.util.ExpressionEnrichmentUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +import java.math.BigDecimal; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + + +@RunWith(MockitoJUnitRunner.class) +public class GenericAssayEnrichmentServiceImplTest extends BaseServiceImplTest{ + @InjectMocks + private ExpressionEnrichmentServiceImpl expressionEnrichmentServiceImpl; + @Mock + private SampleService sampleService; + @Mock + private MolecularProfileService molecularProfileService; + @Mock + private MolecularDataRepository molecularDataRepository; + + @Mock + private GenericAssayService genericAssayService; + + @Spy + @InjectMocks + private ExpressionEnrichmentUtil expressionEnrichmentUtil; + + CancerStudy cancerStudy = new CancerStudy(); + MolecularProfile geneMolecularProfile = new MolecularProfile(); + MolecularProfileSamples molecularProfileSamples = new MolecularProfileSamples(); + List samples = new ArrayList<>(); + Map> molecularProfileCaseSets = new HashMap<>(); + Map> molecularProfilePatientLevelCaseSets = new HashMap<>(); + // patient level only data + public static final String SAMPLE_ID5 = "sample_id5"; + + + @Before + public void setup() throws MolecularProfileNotFoundException { + cancerStudy.setReferenceGenome(ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME); + cancerStudy.setCancerStudyIdentifier(STUDY_ID); + + geneMolecularProfile.setCancerStudyIdentifier(STUDY_ID); + geneMolecularProfile.setStableId(MOLECULAR_PROFILE_ID); + + geneMolecularProfile.setCancerStudy(cancerStudy); + + molecularProfileSamples.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularProfileSamples.setCommaSeparatedSampleIds("1,2,3,4"); + + Sample sample1 = new Sample(); + sample1.setStableId(SAMPLE_ID1); + sample1.setInternalId(1); + sample1.setCancerStudyIdentifier(STUDY_ID); + sample1.setPatientId(1); + samples.add(sample1); + Sample sample2 = new Sample(); + sample2.setStableId(SAMPLE_ID2); + sample2.setInternalId(2); + sample2.setCancerStudyIdentifier(STUDY_ID); + sample2.setPatientId(2); + samples.add(sample2); + Sample sample3 = new Sample(); + sample3.setStableId(SAMPLE_ID3); + sample3.setInternalId(3); + sample3.setCancerStudyIdentifier(STUDY_ID); + sample3.setPatientId(3); + samples.add(sample3); + Sample sample4 = new Sample(); + sample4.setStableId(SAMPLE_ID4); + sample4.setInternalId(4); + sample4.setCancerStudyIdentifier(STUDY_ID); + sample4.setPatientId(4); + samples.add(sample4); + + List alteredSampleIdentifieres = new ArrayList<>(); + List unalteredSampleIdentifieres = new ArrayList<>(); + List unalteredPatientLevelSampleIdentifieres = new ArrayList<>(); + + MolecularProfileCaseIdentifier caseIdentifier1 = new MolecularProfileCaseIdentifier(); + caseIdentifier1.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier1.setCaseId(SAMPLE_ID1); + alteredSampleIdentifieres.add(caseIdentifier1); + + MolecularProfileCaseIdentifier caseIdentifier2 = new MolecularProfileCaseIdentifier(); + caseIdentifier2.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier2.setCaseId(SAMPLE_ID2); + alteredSampleIdentifieres.add(caseIdentifier2); + + MolecularProfileCaseIdentifier caseIdentifier3 = new MolecularProfileCaseIdentifier(); + caseIdentifier3.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier3.setCaseId(SAMPLE_ID3); + unalteredSampleIdentifieres.add(caseIdentifier3); + unalteredPatientLevelSampleIdentifieres.add(caseIdentifier3); + + MolecularProfileCaseIdentifier caseIdentifier4 = new MolecularProfileCaseIdentifier(); + caseIdentifier4.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier4.setCaseId(SAMPLE_ID4); + unalteredSampleIdentifieres.add(caseIdentifier4); + unalteredPatientLevelSampleIdentifieres.add(caseIdentifier4); + + // patient level only data + MolecularProfileCaseIdentifier caseIdentifier5 = new MolecularProfileCaseIdentifier(); + caseIdentifier5.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier5.setCaseId(SAMPLE_ID5); + unalteredPatientLevelSampleIdentifieres.add(caseIdentifier5); + + molecularProfileCaseSets.put("altered samples", alteredSampleIdentifieres); + molecularProfileCaseSets.put("unaltered samples", unalteredSampleIdentifieres); + molecularProfilePatientLevelCaseSets.put("altered samples", alteredSampleIdentifieres); + molecularProfilePatientLevelCaseSets.put("unaltered samples", unalteredPatientLevelSampleIdentifieres); + + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(geneMolecularProfile); + + Mockito.when(molecularDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfileSamples); + + Mockito.when(sampleService.fetchSamples(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), + Arrays.asList(SAMPLE_ID3, SAMPLE_ID4, SAMPLE_ID1, SAMPLE_ID2), "ID")).thenReturn(samples); + } + + @Test + public void getGenericAssayBinaryEnrichments() throws Exception { + geneMolecularProfile.setMolecularAlterationType(MolecularProfile.MolecularAlterationType.GENERIC_ASSAY); + geneMolecularProfile.setDatatype("BINARY"); + List molecularDataList = new ArrayList(); + GenericAssayMolecularAlteration genericAssayMolecularAlteration1 = new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration1.setGenericAssayStableId(HUGO_GENE_SYMBOL_1); + + // here are 2 groups + genericAssayMolecularAlteration1.setValues("true,true,true,false"); + molecularDataList.add(genericAssayMolecularAlteration1); + + GenericAssayMolecularAlteration genericAssayMolecularAlteration2 = new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration2.setGenericAssayStableId(HUGO_GENE_SYMBOL_2); + genericAssayMolecularAlteration2.setValues("true,false,false,true"); + molecularDataList.add(genericAssayMolecularAlteration2); + Mockito.when(molecularDataRepository.getGenericAssayMolecularAlterationsIterable(MOLECULAR_PROFILE_ID, null, + "SUMMARY")).thenReturn(molecularDataList); + + Mockito.when(genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + Arrays.asList(HUGO_GENE_SYMBOL_1, HUGO_GENE_SYMBOL_2), + Arrays.asList(MOLECULAR_PROFILE_ID, MOLECULAR_PROFILE_ID), "SUMMARY")) + .thenReturn(Arrays.asList(new GenericAssayMeta(HUGO_GENE_SYMBOL_1), + new GenericAssayMeta(HUGO_GENE_SYMBOL_2))); + + List result = expressionEnrichmentServiceImpl.getGenericAssayBinaryEnrichments(MOLECULAR_PROFILE_ID, + molecularProfileCaseSets, EnrichmentType.SAMPLE); + + Assert.assertEquals(2, result.size()); + GenericAssayBinaryEnrichment genericAssayBinaryEnrichment = result.get(0); + Assert.assertEquals(HUGO_GENE_SYMBOL_1, genericAssayBinaryEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayBinaryEnrichment.getGroupsStatistics().size()); + + GroupStatistics unalteredGroupStats = genericAssayBinaryEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("0.5"), unalteredGroupStats.getMeanExpression()); + Assert.assertEquals(new BigDecimal("0.7071067811865476"), unalteredGroupStats.getStandardDeviation()); + + GroupStatistics alteredGroupStats = genericAssayBinaryEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("1.0"), alteredGroupStats.getMeanExpression()); + Assert.assertEquals(new BigDecimal("0.0"), alteredGroupStats.getStandardDeviation()); + + Assert.assertEquals(new BigDecimal("0.49999999999999983"), genericAssayBinaryEnrichment.getpValue()); + Assert.assertEquals(new BigDecimal("0.99999999999999966"), genericAssayBinaryEnrichment.getqValue()); + + genericAssayBinaryEnrichment = result.get(1); + Assert.assertEquals(HUGO_GENE_SYMBOL_2, genericAssayBinaryEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayBinaryEnrichment.getGroupsStatistics().size()); + + unalteredGroupStats = genericAssayBinaryEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("0.5"), unalteredGroupStats.getMeanExpression()); + Assert.assertEquals(new BigDecimal("0.7071067811865476"), unalteredGroupStats.getStandardDeviation()); + + alteredGroupStats = genericAssayBinaryEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("0.5"), alteredGroupStats.getMeanExpression()); + Assert.assertEquals(new BigDecimal("0.7071067811865476"), alteredGroupStats.getStandardDeviation()); + + Assert.assertEquals(new BigDecimal("1.0"), genericAssayBinaryEnrichment.getpValue()); + Assert.assertEquals(new BigDecimal("1.0"), genericAssayBinaryEnrichment.getqValue()); + } + + + @Test + public void getGenericAssayCategoricalEnrichments() throws MolecularProfileNotFoundException { + geneMolecularProfile.setMolecularAlterationType(MolecularProfile.MolecularAlterationType.GENERIC_ASSAY); + geneMolecularProfile.setDatatype("CATEGORICAL"); + List molecularDataList = new ArrayList(); + GenericAssayMolecularAlteration genericAssayMolecularAlteration1 = new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration1.setGenericAssayStableId(HUGO_GENE_SYMBOL_1); + genericAssayMolecularAlteration1.setValues("category1,category1,category2,category2"); + molecularDataList.add(genericAssayMolecularAlteration1); + + GenericAssayMolecularAlteration genericAssayMolecularAlteration2 = new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration2.setGenericAssayStableId(HUGO_GENE_SYMBOL_2); + genericAssayMolecularAlteration2.setValues("category2,category2,category1,category1"); + molecularDataList.add(genericAssayMolecularAlteration2); + Mockito.when(molecularDataRepository.getGenericAssayMolecularAlterationsIterable(MOLECULAR_PROFILE_ID, null, + "SUMMARY")).thenReturn(molecularDataList); + + Mockito.when(genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + Arrays.asList(HUGO_GENE_SYMBOL_1, HUGO_GENE_SYMBOL_2), + Arrays.asList(MOLECULAR_PROFILE_ID, MOLECULAR_PROFILE_ID), "SUMMARY")) + .thenReturn(Arrays.asList(new GenericAssayMeta(HUGO_GENE_SYMBOL_1), + new GenericAssayMeta(HUGO_GENE_SYMBOL_2))); + + List result = expressionEnrichmentServiceImpl.getGenericAssayCategoricalEnrichments(MOLECULAR_PROFILE_ID, + molecularProfileCaseSets, EnrichmentType.SAMPLE); + + Assert.assertEquals(2, result.size()); + GenericAssayCategoricalEnrichment genericAssayCategoricalEnrichment = result.get(0); + Assert.assertEquals(HUGO_GENE_SYMBOL_1, genericAssayCategoricalEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayCategoricalEnrichment.getGroupsStatistics().size()); + + GroupStatistics unalteredGroupStats = genericAssayCategoricalEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + + GroupStatistics alteredGroupStats = genericAssayCategoricalEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + + Assert.assertEquals(new BigDecimal("0.04550026389635764"), genericAssayCategoricalEnrichment.getpValue()); + Assert.assertEquals(new BigDecimal("0.04550026389635764"), genericAssayCategoricalEnrichment.getqValue()); + + genericAssayCategoricalEnrichment = result.get(1); + Assert.assertEquals(HUGO_GENE_SYMBOL_2, genericAssayCategoricalEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayCategoricalEnrichment.getGroupsStatistics().size()); + + unalteredGroupStats = genericAssayCategoricalEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + + alteredGroupStats = genericAssayCategoricalEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + + Assert.assertEquals(new BigDecimal("0.04550026389635764"), genericAssayCategoricalEnrichment.getpValue()); + Assert.assertEquals(new BigDecimal("0.04550026389635764"), genericAssayCategoricalEnrichment.getqValue()); + } + +} diff --git a/service/src/test/java/org/cbioportal/service/impl/StudyViewServiceImplTest.java b/service/src/test/java/org/cbioportal/service/impl/StudyViewServiceImplTest.java index 446681badcf..801ab8afebf 100644 --- a/service/src/test/java/org/cbioportal/service/impl/StudyViewServiceImplTest.java +++ b/service/src/test/java/org/cbioportal/service/impl/StudyViewServiceImplTest.java @@ -14,10 +14,7 @@ import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; import static org.mockito.ArgumentMatchers.*; @@ -41,6 +38,10 @@ public class StudyViewServiceImplTest extends BaseServiceImplTest { private SignificantCopyNumberRegionService significantCopyNumberRegionService; @Mock private GenericAssayService genericAssayService; + @Mock + private MolecularDataService molecularDataService; + @Mock + private GeneService geneService; private AlterationFilter alterationFilter = new AlterationFilter(); @Test @@ -174,7 +175,7 @@ public void getMutationAlterationCountByGenes() throws Exception { alterationCountByGene1.setTotalCount(2); alterationCountByGene1.setNumberOfProfiledCases(2); alterationCountByGenes.add(alterationCountByGene1); - Mockito.when(alterationCountService.getSampleMutationCounts(molecularProfileCaseIdentifiers, + Mockito.when(alterationCountService.getSampleMutationGeneCounts(molecularProfileCaseIdentifiers, Select.all(), true, false, @@ -208,7 +209,7 @@ public void getStructuralVariantAlterationCountByGenes() throws Exception { alterationCountByGene1.setTotalCount(2); alterationCountByGene1.setNumberOfProfiledCases(2); alterationCountByGenes.add(alterationCountByGene1); - Mockito.when(alterationCountService.getSampleStructuralVariantCounts( + Mockito.when(alterationCountService.getSampleStructuralVariantGeneCounts( molecularProfileCaseIdentifiers, Select.all(), true, @@ -245,7 +246,7 @@ public void getCNAAlterationCountByGenes() throws Exception { alterationCountByGene1.setAlteration(2); alterationCountByGenes.add(alterationCountByGene1); - Mockito.when(alterationCountService.getSampleCnaCounts( + Mockito.when(alterationCountService.getSampleCnaGeneCounts( anyList(), any(Select.class), anyBoolean(), @@ -255,6 +256,79 @@ public void getCNAAlterationCountByGenes() throws Exception { Assert.assertEquals(1, result.size()); } + @Test + public void getCNAAlterationCountByGeneSpecific() throws Exception { + + List sampleIds = Arrays.asList(BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.SAMPLE_ID2, BaseServiceImplTest.SAMPLE_ID3); + List studyIds = Collections.nCopies(3, BaseServiceImplTest.STUDY_ID); + List> genomicDataFilters = new ArrayList<>(); + Pair genomicDataFilter1 = new Pair<>(BaseServiceImplTest.HUGO_GENE_SYMBOL_1, BaseServiceImplTest.PROFILE_TYPE_1); + Pair genomicDataFilter2 = new Pair<>(BaseServiceImplTest.HUGO_GENE_SYMBOL_2, BaseServiceImplTest.PROFILE_TYPE_2); + genomicDataFilters.add(genomicDataFilter1); + genomicDataFilters.add(genomicDataFilter2); + + List molecularProfiles = new ArrayList<>(); + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + molecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_" + BaseServiceImplTest.MOLECULAR_PROFILE_ID_A); + molecularProfiles.add(molecularProfile); + + Mockito.when(molecularProfileService.getMolecularProfilesInStudies(studyIds, "SUMMARY")) + .thenReturn(molecularProfiles); + + Map> molecularProfileMap = new HashMap<>(); + molecularProfileMap.put(BaseServiceImplTest.PROFILE_TYPE_1, molecularProfiles); + molecularProfileMap.put(BaseServiceImplTest.PROFILE_TYPE_2, molecularProfiles); + + Mockito.when(molecularProfileUtil.categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles)) + .thenReturn(molecularProfileMap); + + List genes = new ArrayList<>(); + Gene gene1 = new Gene(); + gene1.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_1); + gene1.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + Gene gene2 = new Gene(); + gene2.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_2); + gene2.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_2); + genes.add(gene1); + genes.add(gene2); + + Mockito.when(geneService.fetchGenes(anyList(), anyString(), anyString())) + .thenReturn(genes); + + List geneMolecularData = new ArrayList<>(); + GeneMolecularData geneMolecularData1 = new GeneMolecularData(); + geneMolecularData1.setValue("-2"); + GeneMolecularData geneMolecularData2 = new GeneMolecularData(); + geneMolecularData2.setValue("-2"); + GeneMolecularData geneMolecularData3 = new GeneMolecularData(); + geneMolecularData3.setValue("2"); + GeneMolecularData geneMolecularData4 = new GeneMolecularData(); + geneMolecularData4.setValue("2"); + geneMolecularData.add(geneMolecularData1); + geneMolecularData.add(geneMolecularData2); + geneMolecularData.add(geneMolecularData3); + geneMolecularData.add(geneMolecularData4); + + Mockito.when(molecularDataService.getMolecularDataInMultipleMolecularProfiles( + anyList(), + anyList(), + anyList(), + anyString())) + .thenReturn(geneMolecularData); + + List result = studyViewService.getCNAAlterationCountsByGeneSpecific(studyIds, sampleIds, genomicDataFilters); + Assert.assertEquals(2, result.size()); + Assert.assertEquals(BaseServiceImplTest.HUGO_GENE_SYMBOL_1, result.get(0).getHugoGeneSymbol()); + Assert.assertEquals(BaseServiceImplTest.PROFILE_TYPE_1, result.get(0).getProfileType()); + Assert.assertEquals(2, result.get(0).getCounts().get(0).getCount().intValue()); + Assert.assertEquals(2, result.get(0).getCounts().get(1).getCount().intValue()); + Assert.assertEquals(BaseServiceImplTest.HUGO_GENE_SYMBOL_2, result.get(1).getHugoGeneSymbol()); + Assert.assertEquals(BaseServiceImplTest.PROFILE_TYPE_2, result.get(1).getProfileType()); + Assert.assertEquals(2, result.get(1).getCounts().get(0).getCount().intValue()); + Assert.assertEquals(2, result.get(1).getCounts().get(1).getCount().intValue()); + } + @Test public void fetchGenericAssayDataCounts() throws Exception { diff --git a/service/src/test/java/org/cbioportal/service/impl/TreatmentServiceImplTest.java b/service/src/test/java/org/cbioportal/service/impl/TreatmentServiceImplTest.java index 9b489f16690..8a86e465d3f 100644 --- a/service/src/test/java/org/cbioportal/service/impl/TreatmentServiceImplTest.java +++ b/service/src/test/java/org/cbioportal/service/impl/TreatmentServiceImplTest.java @@ -26,14 +26,11 @@ public class TreatmentServiceImplTest { private TreatmentRepository treatmentRepository; @Test - public void getAllSampleTreatmentsSingleRow() { - mockTreatmentsByPatient( - makeTreatment("madeupanib", "P0", 0, 10) - ); + public void getAllPatientTreatmentRows() { mockSamplesByPatient( makeSample("S0", "P0", 5) ); - mockAllTreatments("madeupanib"); + mockTreatments(makeTreatment("madeupanib", "P0", 0, 10)); PatientTreatmentRow rowA = makePatientRow("madeupanib", 1, Collections.singletonList("S0"), Collections.singletonList("P0")); List expected = Collections.singletonList(rowA); @@ -43,15 +40,14 @@ public void getAllSampleTreatmentsSingleRow() { } @Test - public void getAllSampleTreatmentsOneSampleTwoTreatmentsOnePatient() { - mockTreatmentsByPatient( + public void getAllPatientTreatmentRowsOneSampleTwoTreatmentsOnePatient() { + mockTreatments( makeTreatment("madeupanib", "P0", 0, 10), makeTreatment("fakedrugazol", "P0", 0, 10) ); mockSamplesByPatient( makeSample("S0", "P0", 5) ); - mockAllTreatments("madeupanib", "fakedrugazol"); PatientTreatmentRow rowA = makePatientRow("fakedrugazol", 1, Collections.singletonList("S0"), Collections.singletonList("P0")); @@ -63,15 +59,14 @@ public void getAllSampleTreatmentsOneSampleTwoTreatmentsOnePatient() { } @Test - public void getAllSampleTreatmentsTwoSamplesOnePatientOneTreatment() { - mockTreatmentsByPatient( + public void getAllPatientTreatmentRowsTwoSamplesOnePatientOneTreatment() { + mockTreatments( makeTreatment("fakedrugazol", "P0", 0, 10) ); mockSamplesByPatient( makeSample("S0", "P0", 5), makeSample("S1", "P0", 10) ); - mockAllTreatments("fakedrugazol"); // even though there are two samples, you expect a count of 1, // because this is from the patient level, and both samples are for the same patient @@ -83,8 +78,8 @@ public void getAllSampleTreatmentsTwoSamplesOnePatientOneTreatment() { } @Test - public void getAllSampleTreatmentsTwoSamplesTwoPatientsTwoTreatments() { - mockTreatmentsByPatient( + public void getAllPatientTreatmentRowsTwoSamplesTwoPatientsTwoTreatments() { + mockTreatments( makeTreatment("fakedrugazol", "P0", 0, 10), makeTreatment("fakedrugazol", "P1", 0, 10) ); @@ -92,7 +87,6 @@ public void getAllSampleTreatmentsTwoSamplesTwoPatientsTwoTreatments() { makeSample("S0", "P0", 5), makeSample("S1", "P1", 10) ); - mockAllTreatments("fakedrugazol"); // now there are two patients, so you expect a count of two PatientTreatmentRow rowA = makePatientRow("fakedrugazol", 2, Arrays.asList("S0", "S1"), Arrays.asList("P0", "P1")); @@ -103,8 +97,8 @@ public void getAllSampleTreatmentsTwoSamplesTwoPatientsTwoTreatments() { } @Test - public void getAllSampleTreatmentsTwoSamplesTwoPatientsTwoDifferentTreatments() { - mockTreatmentsByPatient( + public void getAllPatientTreatmentRowsTwoSamplesTwoPatientsTwoDifferentTreatments() { + mockTreatments( makeTreatment("fakedrugazol", "P0", 0, 10), makeTreatment("madeupanib", "P1", 0, 10) ); @@ -112,7 +106,6 @@ public void getAllSampleTreatmentsTwoSamplesTwoPatientsTwoDifferentTreatments() makeSample("S0", "P0", 5), makeSample("S1", "P1", 10) ); - mockAllTreatments("fakedrugazol", "madeupanib"); PatientTreatmentRow rowA = makePatientRow("fakedrugazol", 1, Collections.singletonList("S0"), Collections.singletonList("P0")); PatientTreatmentRow rowB = makePatientRow("madeupanib", 1, Collections.singletonList("S1"), Collections.singletonList("P1")); @@ -252,6 +245,11 @@ private void mockTreatmentsByPatient(Treatment... treatments) { .thenReturn(treatmentsByPatient); } + private void mockTreatments(Treatment... treatments) { + Mockito.when(treatmentRepository.getTreatments(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(Arrays.stream(treatments).collect(Collectors.toList())); + } + private void mockSamplesByPatient(ClinicalEventSample... samples) { Map> samplesByPatient = Arrays.stream(samples) .collect(Collectors.groupingBy(ClinicalEventSample::getPatientId)); @@ -261,12 +259,6 @@ private void mockSamplesByPatient(ClinicalEventSample... samples) { .thenReturn(samplesByPatient); } - private void mockAllTreatments(String... treatments) { - Set allTreatments = new HashSet<>(Arrays.asList(treatments)); - Mockito.when(treatmentRepository.getAllUniqueTreatments(Mockito.any(), Mockito.any(), Mockito.any())) - .thenReturn(allTreatments); - } - private Treatment makeTreatment(String treatment, String patientId, Integer start, Integer stop) { Treatment t = new Treatment(); t.setTreatment(treatment); diff --git a/service/src/test/java/org/cbioportal/service/util/AlterationEnrichmentUtilTest.java b/service/src/test/java/org/cbioportal/service/util/AlterationEnrichmentUtilTest.java index 71aab65f880..7020d01ef0e 100644 --- a/service/src/test/java/org/cbioportal/service/util/AlterationEnrichmentUtilTest.java +++ b/service/src/test/java/org/cbioportal/service/util/AlterationEnrichmentUtilTest.java @@ -101,8 +101,8 @@ public void createAlterationEnrichments() throws Exception { // START: for 2 groups - Mockito.when(fisherExactTestCalculator.getCumulativePValue(1, 1, 2, 0)).thenReturn(1.0); - Mockito.when(fisherExactTestCalculator.getCumulativePValue(2, 0, 0, 2)).thenReturn(0.3); + Mockito.when(fisherExactTestCalculator.getTwoTailedPValue(1, 1, 2, 0)).thenReturn(1.0); + Mockito.when(fisherExactTestCalculator.getTwoTailedPValue(2, 0, 0, 2)).thenReturn(0.3); List result = alterationEnrichmentUtil.createAlterationEnrichments( mutationCountsbyEntrezGeneIdAndGroup); diff --git a/src/main/resources/portal.properties.EXAMPLE b/src/main/resources/portal.properties.EXAMPLE index ce65c322e26..7ad52af6203 100644 --- a/src/main/resources/portal.properties.EXAMPLE +++ b/src/main/resources/portal.properties.EXAMPLE @@ -4,10 +4,8 @@ app.name=cbioportal # database db.user=cbio_user db.password=somepassword -db.host=localhost:3306 -db.portal_db_name=cbioportal db.driver=com.mysql.jdbc.Driver -db.connection_string=jdbc:mysql://localhost:3306/ +db.connection_string=jdbc:mysql://localhost:3306/cbioportal?useSSL=false # set tomcat_resource_name when using dbconnector=jndi instead of the default # dbconnector=dbcp. Note that dbconnector needs to be set in CATLINA_OPTS when # using Tomcat (CATALINA_OPTS="-Ddbconnector=jndi"). It does not get picked up @@ -18,7 +16,7 @@ db.connection_string=jdbc:mysql://localhost:3306/ # this should normally be set to false. In some cases you could set this to true (e.g. for testing a feature of a newer release that is not related to the schema change in expected db version above): db.suppress_schema_version_mismatch_errors=false -db.use_ssl=false + # web page cosmetics skin.title=cBioPortal for Cancer Genomics skin.email_contact=cbioportal at googlegroups dot com @@ -104,16 +102,26 @@ skin.study_view.link_text=To build your own case set, try out our enhanced Study # skin.home_page.show_unauthorized_studies=false ## enable this to configure a global message for the studies that are unauthorized; the message can contain placecards like {$.Owner.email} for the studies that have the information in the study tags # skin.home_page.unauthorized_studies_global_message=The study is unauthorized. You need to request access. +## enable this to show reference genome next to the samples +# skin.home_page.show_reference_genome=false -setting controlling whether Download tabs and download/copy-to-clipboard controls should be shown -# skin.hide_download_controls=true +## setting controlling whether Download tabs and download/copy-to-clipboard controls should be shown +# skin.hide_download_controls=false -setting controlling which name should be used to display the authenticated user (email, or username) +## setting controlling which name should be used to display the authenticated user (email, or username) # skin.user_display_name=email ## enable and set this property to specify a study group to be used to identify public studies for which no specific authorization entries are needed in the `authorities` table # always_show_study_group= +## enable expression data in multi-study queries (oncoprint and plots tab) +# true | false | (studies)=>{ return true } +# enable_cross_study_expression= + +## Combined Study View Comparison Limits +# Any Number | Disabled when not set +# studyview.max_samples_selected= + ## change the `-Dauthenticate=` JVM argument to configure ## which method of authentication to use (false, googleplus, social_auth_google, social_auth_microsoft, saml, openid, noauthsessionservice) @@ -161,6 +169,7 @@ dat.method=none dat.ttl_seconds=2592000 dat.uuid.max_number_per_user=1 dat.jwt.secret_key= +dat.filter_user_role= # OAuth2 token data access settings #dat.oauth2.clientId= @@ -306,6 +315,7 @@ oncoprint.oncokb.default=true oncoprint.hotspots.default=true # oncoprint.hide_vus.default=true # oncoprint.clinical_tracks.config_json=classpath:/oncoprint-default-tracks.json +# oncoprint.clustered.default=true # Custom gene sets # querypage.setsofgenes.location=file:/ @@ -420,3 +430,12 @@ persistence.cache_type=no-cache # Set comparison categorical "NA" value (not case sensitive), separated by "|" # comparison.categorical_na_values=NA|unknown + +# Set StudyDownloadLinkUrl +# Allows download links within DataSets Tab (See Portal.Properties documentation for more info) +# study_download_url= + +# download_group= + +# vaf.sequential_mode.default=false +# vaf.log_scale.default=false diff --git a/test/integration/docker-compose-localbuild.yml b/test/integration/docker-compose-localbuild.yml index d7a0523e8a1..cd3d8adc17e 100644 --- a/test/integration/docker-compose-localbuild.yml +++ b/test/integration/docker-compose-localbuild.yml @@ -10,6 +10,8 @@ services: - $PORTAL_INFO_DIR:/portalinfo/ # make docker compose run the cbioportal version-under-test # by volume mounting the local portal source folder into the container - # and running + # and running - $PORTAL_SOURCE_DIR:/cbioportal/ - $PORTAL_SOURCE_DIR/portal/target/cbioportal.war:/app.war + # TODO: remove line below after upgrade of cbioportal-docker-compose to > v5.3.20 + - $PORTAL_SOURCE_DIR/docker/web-and-data/docker-entrypoint.sh:/usr/local/bin/docker-entrypoint.sh diff --git a/test/integration/test_load_study.sh b/test/integration/test_load_study.sh index d54aef3032e..d0d60663f3e 100755 --- a/test/integration/test_load_study.sh +++ b/test/integration/test_load_study.sh @@ -17,6 +17,8 @@ run_in_service cbioportal "cd /cbioportal/core/src/main/scripts/ && perl importG /cbioportal/core/src/test/scripts/test_data/study_es_0/data_gene_panel_testpanel1.txt" run_in_service cbioportal "cd /cbioportal/core/src/main/scripts/ && perl importGenePanel.pl --data \ /cbioportal/core/src/test/scripts/test_data/study_es_0/data_gene_panel_testpanel2.txt" +run_in_service cbioportal "cd /cbioportal/core/src/main/scripts/ && echo yes | ./importGenesetData.pl --data /cbioportal/core/src/test/resources/genesets/study_es_0_genesets.gmt --new-version msigdb_7.5.1 --supp /cbioportal/core/src/test/resources/genesets/study_es_0_supp-genesets.txt" +run_in_service cbioportal "cd /cbioportal/core/src/main/scripts/ && ./importGenesetHierarchy.pl --data /cbioportal/core/src/test/resources/genesets/study_es_0_tree.yaml" # dump portal info echo "Testing the dump of local portal info directory..." diff --git a/web/pom.xml b/web/pom.xml index 92f14f15f77..6fd0482d0df 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -96,29 +96,6 @@ org.mongodb mongo-java-driver - - com.github.cbioportal - session-service - model - - - org.apache.logging.log4j - log4j-to-slf4j - - - ch.qos.logback - logback-classic - - - spring-boot-starter-web - org.springframework.boot - - - spring-boot-starter-data-mongodb - org.springframework.boot - - - com.fasterxml.jackson.core jackson-databind diff --git a/web/src/main/java/org/cbioportal/web/DataAccessTokenController.java b/web/src/main/java/org/cbioportal/web/DataAccessTokenController.java index e8938209bdb..06ddc00f27e 100644 --- a/web/src/main/java/org/cbioportal/web/DataAccessTokenController.java +++ b/web/src/main/java/org/cbioportal/web/DataAccessTokenController.java @@ -20,7 +20,7 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; -import io.swagger.models.HttpMethod; +import org.apache.commons.lang3.StringUtils; import org.cbioportal.model.DataAccessToken; import org.cbioportal.service.DataAccessTokenService; import org.cbioportal.service.exception.DataAccessTokenNoUserIdentityException; @@ -32,6 +32,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.HttpClientErrorException; @@ -54,6 +55,10 @@ public class DataAccessTokenController { @Value("${dat.unauth_users:anonymousUser}") private String[] USERS_WHO_CANNOT_USE_TOKENS; + private static String userRoleToAccessToken; + @Value("${download_group:}") // default is empty string + public void setUserRoleToAccessToken(String property) { userRoleToAccessToken = property; } + @Autowired private DataAccessTokenService tokenService; private Set usersWhoCannotUseTokenSet; @@ -130,6 +135,10 @@ private String getAuthenticatedUser(Authentication authentication) { if (usersWhoCannotUseTokenSet.contains(username)) { throw new DataAccessTokenProhibitedUserException(); } + if(StringUtils.isNotEmpty(userRoleToAccessToken) && + !authentication.getAuthorities().contains(new SimpleGrantedAuthority(userRoleToAccessToken))) { + throw new DataAccessTokenProhibitedUserException(); + } return username; } } diff --git a/web/src/main/java/org/cbioportal/web/ExpressionEnrichmentController.java b/web/src/main/java/org/cbioportal/web/ExpressionEnrichmentController.java index 0252463e558..4072480eb13 100644 --- a/web/src/main/java/org/cbioportal/web/ExpressionEnrichmentController.java +++ b/web/src/main/java/org/cbioportal/web/ExpressionEnrichmentController.java @@ -95,7 +95,7 @@ private List fetchExpressionEnrichments(Enri } if (isRequestForGenericAssayEnrichments) { - return (List) expressionEnrichmentService.getGenericAssayEnrichments( + return (List) expressionEnrichmentService.getGenericAssayNumericalEnrichments( molecularProfileIds.iterator().next(), groupCaseIdentifierSet, enrichmentType); } diff --git a/web/src/main/java/org/cbioportal/web/GenericAssayEnrichmentController.java b/web/src/main/java/org/cbioportal/web/GenericAssayEnrichmentController.java new file mode 100644 index 00000000000..294c580582e --- /dev/null +++ b/web/src/main/java/org/cbioportal/web/GenericAssayEnrichmentController.java @@ -0,0 +1,116 @@ +package org.cbioportal.web; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import org.cbioportal.model.EnrichmentType; +import org.cbioportal.model.GenericAssayBinaryEnrichment; +import org.cbioportal.model.GenericAssayCategoricalEnrichment; +import org.cbioportal.model.MolecularProfileCaseIdentifier; +import org.cbioportal.service.ExpressionEnrichmentService; +import org.cbioportal.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.web.config.annotation.InternalApi; +import org.cbioportal.web.parameter.MolecularProfileCasesGroupFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestAttribute; +import springfox.documentation.annotations.ApiIgnore; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +@InternalApi +@RestController +@Validated +@Api(tags = "Generic Assay Enrichment Data", description = " ") +public class GenericAssayEnrichmentController { + @Autowired + private ExpressionEnrichmentService expressionEnrichmentService; + + @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") + @RequestMapping(value = "/generic-assay-categorical-enrichments/fetch", + method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @ApiOperation("Fetch generic assay categorical data enrichments in a molecular profile") + public ResponseEntity> fetchGenericAssayCategoricalDataEnrichmentInMultipleMolecularProfiles( + @ApiIgnore + @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, + @ApiParam("Type of the enrichment e.g. SAMPLE or PATIENT") + @RequestParam(defaultValue = "SAMPLE") EnrichmentType enrichmentType, + @ApiParam(required = true, value = "List of groups containing sample and molecular profile identifiers") + @Valid @RequestBody(required = false) List groups, + @ApiIgnore + @Valid @RequestAttribute(required = false, value = "interceptedMolecularProfileCasesGroupFilters") List interceptedMolecularProfileCasesGroupFilters) + throws MolecularProfileNotFoundException, UnsupportedOperationException { + + return new ResponseEntity<>(fetchExpressionEnrichments(enrichmentType, interceptedMolecularProfileCasesGroupFilters), + HttpStatus.OK); + } + + @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") + @RequestMapping(value = "/generic-assay-binary-enrichments/fetch", + method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @ApiOperation("Fetch generic assay binary data enrichments in a molecular profile") + public ResponseEntity> fetchGenericAssayBinaryDataEnrichmentInMultipleMolecularProfiles( + @ApiIgnore + @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, + @ApiParam("Type of the enrichment e.g. SAMPLE or PATIENT") + @RequestParam(defaultValue = "SAMPLE") EnrichmentType enrichmentType, + @ApiParam(required = true, value = "List of groups containing sample and molecular profile identifiers") + @Valid @RequestBody(required = false) List groups, + @ApiIgnore + @Valid @RequestAttribute(required = false, value = "interceptedMolecularProfileCasesGroupFilters") List interceptedMolecularProfileCasesGroupFilters) + throws MolecularProfileNotFoundException, UnsupportedOperationException { + + Map> groupCaseIdentifierSet = interceptedMolecularProfileCasesGroupFilters + .stream().collect(Collectors.toMap(MolecularProfileCasesGroupFilter::getName, + MolecularProfileCasesGroupFilter::getMolecularProfileCaseIdentifiers)); + + Set molecularProfileIds = groupCaseIdentifierSet.values().stream() + .flatMap(molecularProfileCaseSet -> molecularProfileCaseSet.stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId)) + .collect(Collectors.toSet()); + + if (molecularProfileIds.size() > 1) { + throw new UnsupportedOperationException("Multi-study enrichments is not yet implemented"); + } + + return new ResponseEntity<>( + expressionEnrichmentService.getGenericAssayBinaryEnrichments( + molecularProfileIds.iterator().next(), groupCaseIdentifierSet, enrichmentType), + HttpStatus.OK); + } + + private List fetchExpressionEnrichments(EnrichmentType enrichmentType, + List interceptedMolecularProfileCasesGroupFilters + ) throws MolecularProfileNotFoundException { + Map> groupCaseIdentifierSet = interceptedMolecularProfileCasesGroupFilters + .stream().collect(Collectors.toMap(MolecularProfileCasesGroupFilter::getName, + MolecularProfileCasesGroupFilter::getMolecularProfileCaseIdentifiers)); + + Set molecularProfileIds = groupCaseIdentifierSet.values().stream() + .flatMap(molecularProfileCaseSet -> molecularProfileCaseSet.stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId)) + .collect(Collectors.toSet()); + + if (molecularProfileIds.size() > 1) { + throw new UnsupportedOperationException("Multi-study expression enrichments is not yet implemented"); + } + return expressionEnrichmentService.getGenericAssayCategoricalEnrichments( + molecularProfileIds.iterator().next(), groupCaseIdentifierSet, enrichmentType); + } +} diff --git a/web/src/main/java/org/cbioportal/web/OAuth2DataAccessTokenController.java b/web/src/main/java/org/cbioportal/web/OAuth2DataAccessTokenController.java index 528f59ae5a6..1b98a12abbc 100644 --- a/web/src/main/java/org/cbioportal/web/OAuth2DataAccessTokenController.java +++ b/web/src/main/java/org/cbioportal/web/OAuth2DataAccessTokenController.java @@ -35,8 +35,10 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; +import org.apache.commons.lang3.StringUtils; import org.cbioportal.model.DataAccessToken; import org.cbioportal.service.DataAccessTokenService; +import org.cbioportal.service.exception.DataAccessTokenNoUserIdentityException; import org.cbioportal.service.exception.DataAccessTokenProhibitedUserException; import org.cbioportal.web.config.annotation.InternalApi; import org.springframework.beans.factory.annotation.Autowired; @@ -46,6 +48,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.HttpClientErrorException; @@ -76,6 +79,9 @@ public class OAuth2DataAccessTokenController { @Value("${dat.oauth2.clientId}") private String clientId; + @Value("${dat.filter_user_role:}") // default is empty string + private String userRoleToAccessToken; + @Autowired private DataAccessTokenService tokenService; private String authorizationUrl; @@ -98,6 +104,8 @@ public void postConstruct() throws UnsupportedEncodingException { public ResponseEntity downloadDataAccessToken(Authentication authentication, HttpServletRequest request, HttpServletResponse response) throws IOException { + isUserAuthorizedToAccess(authentication); + // redirect to authentication endpoint HttpHeaders headers = new HttpHeaders(); headers.add("Location", authorizationUrl); @@ -156,4 +164,15 @@ public void revokeDataAccessToken(@ApiParam(required = true, value = "token") @P throw new UnsupportedOperationException("this endpoint is does not apply to OAuth2 data access token method."); } + private void isUserAuthorizedToAccess(Authentication authentication) { + if (authentication == null || !authentication.isAuthenticated()) { + throw new DataAccessTokenNoUserIdentityException(); + } + + if(StringUtils.isNotEmpty(userRoleToAccessToken) && + !authentication.getAuthorities().contains(new SimpleGrantedAuthority(userRoleToAccessToken))) { + throw new DataAccessTokenProhibitedUserException(); + } + } + } diff --git a/web/src/main/java/org/cbioportal/web/SessionServiceController.java b/web/src/main/java/org/cbioportal/web/SessionServiceController.java index 64fe9f4a89f..576f44a9c6d 100644 --- a/web/src/main/java/org/cbioportal/web/SessionServiceController.java +++ b/web/src/main/java/org/cbioportal/web/SessionServiceController.java @@ -8,10 +8,12 @@ import javax.validation.constraints.Size; import com.google.common.collect.ImmutableMap; +import org.cbioportal.service.util.CustomAttributeWithData; +import org.cbioportal.service.util.CustomDataSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.cbioportal.web.parameter.*; -import org.cbioportal.web.util.SessionServiceRequestHandler; +import org.cbioportal.service.util.SessionServiceRequestHandler; import org.cbioportal.session_service.domain.Session; import org.cbioportal.session_service.domain.SessionType; import org.json.simple.JSONObject; @@ -48,6 +50,9 @@ public class SessionServiceController { @Autowired SessionServiceRequestHandler sessionServiceRequestHandler; + @Autowired + private ObjectMapper sessionServiceObjectMapper; + @Value("${session.service.url:}") private String sessionServiceURL; @@ -106,11 +111,9 @@ private ResponseEntity addSession( ) { try { HttpEntity httpEntity; - ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, - false); if (type.equals(SessionType.virtual_study) || type.equals(SessionType.group)) { // JSON from file to Object - VirtualStudyData virtualStudyData = mapper.readValue(body.toString(), VirtualStudyData.class); + VirtualStudyData virtualStudyData = sessionServiceObjectMapper.readValue(body.toString(), VirtualStudyData.class); if (isAuthorized()) { virtualStudyData.setOwner(userName()); @@ -129,7 +132,7 @@ private ResponseEntity addSession( Class pageDataClass = pageToSettingsDataClass.get( SessionPage.valueOf((String) body.get("page")) ); - PageSettingsData pageSettings = mapper.readValue( + PageSettingsData pageSettings = sessionServiceObjectMapper.readValue( body.toString(), pageDataClass ); @@ -138,7 +141,7 @@ private ResponseEntity addSession( } else if(type.equals(SessionType.custom_data)) { // JSON from file to Object - CustomAttributeWithData customData = mapper.readValue(body.toString(), CustomAttributeWithData.class); + CustomAttributeWithData customData = sessionServiceObjectMapper.readValue(body.toString(), CustomAttributeWithData.class); if (isAuthorized()) { customData.setOwner(userName()); @@ -151,7 +154,7 @@ private ResponseEntity addSession( if (!(isAuthorized())) { return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); } - CustomGeneListData customGeneListData = mapper.readValue(body.toString(), CustomGeneListData.class); + CustomGeneListData customGeneListData = sessionServiceObjectMapper.readValue(body.toString(), CustomGeneListData.class); customGeneListData.setUsers(Collections.singleton(userName())); httpEntity = new HttpEntity<>(customGeneListData, sessionServiceRequestHandler.getHttpHeaders()); } else { @@ -177,9 +180,25 @@ private ResponseEntity addSession( public ResponseEntity getSession(@PathVariable SessionType type, @PathVariable String id) { try { - Session session = sessionServiceRequestHandler.getSession(type, id); + String sessionDataJson = sessionServiceRequestHandler.getSessionDataJson(type, id); + Session session; + switch (type) { + case virtual_study: + session = sessionServiceObjectMapper.readValue(sessionDataJson, VirtualStudy.class); + break; + case settings: + session = sessionServiceObjectMapper.readValue(sessionDataJson, PageSettings.class); + break; + case custom_data: + session = sessionServiceObjectMapper.readValue(sessionDataJson, CustomDataSession.class); + break; + case custom_gene_list: + session = sessionServiceObjectMapper.readValue(sessionDataJson, CustomGeneList.class); + break; + default: + session = sessionServiceObjectMapper.readValue(sessionDataJson, Session.class); + } return new ResponseEntity<>(session, HttpStatus.OK); - } catch (Exception exception) { LOG.error("Error occurred", exception); return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); @@ -232,28 +251,26 @@ public void updateUsersInSession(@PathVariable SessionType type, @PathVariable S @PathVariable Operation operation, HttpServletResponse response) throws IOException { if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { - ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, - false); HttpEntity httpEntity; if (type.equals(SessionType.custom_data)) { - String virtualStudyStr = mapper.writeValueAsString(getSession(type, id).getBody()); - CustomDataSession customDataSession = mapper.readValue(virtualStudyStr, CustomDataSession.class); + String virtualStudyStr = sessionServiceObjectMapper.writeValueAsString(getSession(type, id).getBody()); + CustomDataSession customDataSession = sessionServiceObjectMapper.readValue(virtualStudyStr, CustomDataSession.class); CustomAttributeWithData customAttributeWithData = customDataSession.getData(); Set users = customAttributeWithData.getUsers(); updateUserList(operation, users); customAttributeWithData.setUsers(users); httpEntity = new HttpEntity<>(customAttributeWithData, sessionServiceRequestHandler.getHttpHeaders()); } else if (type.equals(SessionType.custom_gene_list)) { - String customGeneListStr = mapper.writeValueAsString(getSession(type, id).getBody()); - CustomGeneList customGeneList = mapper.readValue(customGeneListStr, CustomGeneList.class); + String customGeneListStr = sessionServiceObjectMapper.writeValueAsString(getSession(type, id).getBody()); + CustomGeneList customGeneList = sessionServiceObjectMapper.readValue(customGeneListStr, CustomGeneList.class); CustomGeneListData customGeneListData = customGeneList.getData(); Set users = customGeneListData.getUsers(); updateUserList(operation, users); customGeneListData.setUsers(users); httpEntity = new HttpEntity<>(customGeneListData, sessionServiceRequestHandler.getHttpHeaders()); } else { - String virtualStudyStr = mapper.writeValueAsString(getSession(type, id).getBody()); - VirtualStudy virtualStudy = mapper.readValue(virtualStudyStr, VirtualStudy.class); + String virtualStudyStr = sessionServiceObjectMapper.writeValueAsString(getSession(type, id).getBody()); + VirtualStudy virtualStudy = sessionServiceObjectMapper.readValue(virtualStudyStr, VirtualStudy.class); VirtualStudyData virtualStudyData = virtualStudy.getData(); Set users = virtualStudyData.getUsers(); updateUserList(operation, users); diff --git a/web/src/main/java/org/cbioportal/web/StudyController.java b/web/src/main/java/org/cbioportal/web/StudyController.java index dc194549f3e..faf514f645f 100644 --- a/web/src/main/java/org/cbioportal/web/StudyController.java +++ b/web/src/main/java/org/cbioportal/web/StudyController.java @@ -23,6 +23,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -98,9 +99,10 @@ public ResponseEntity> getAllStudies( @ApiParam("Name of the property that the result list is sorted by") @RequestParam(required = false) StudySortBy sortBy, @ApiParam("Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction, - Authentication authentication) { - + @RequestParam(defaultValue = "ASC") Direction direction) + { + + Authentication authentication = null; // Only use this feature on the public portal and make sure it is never used // on portals using auth, as in auth setting, different users will have different // results. @@ -114,6 +116,8 @@ public ResponseEntity> getAllStudies( && direction == Direction.ASC) { return new ResponseEntity<>(defaultResponse, HttpStatus.OK); } + else + authentication = SecurityContextHolder.getContext().getAuthentication(); if (projection == Projection.META) { HttpHeaders responseHeaders = new HttpHeaders(); @@ -185,7 +189,8 @@ public ResponseEntity getTags( @ApiOperation("Get the study tags by IDs") public ResponseEntity> getTagsForMultipleStudies( @ApiParam(required = true, value = "List of Study IDs") - @RequestBody List studyIds) { + @RequestBody List studyIds + ) { List cancerStudyTags = studyService.getTagsForMultipleStudies(studyIds); diff --git a/web/src/main/java/org/cbioportal/web/StudyViewController.java b/web/src/main/java/org/cbioportal/web/StudyViewController.java index 22a12871b3f..f4ca464cf50 100644 --- a/web/src/main/java/org/cbioportal/web/StudyViewController.java +++ b/web/src/main/java/org/cbioportal/web/StudyViewController.java @@ -9,6 +9,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.math3.stat.correlation.PearsonsCorrelation; import org.apache.commons.math3.stat.correlation.SpearmansCorrelation; +import org.apache.commons.math3.util.Pair; import org.cbioportal.model.*; import org.cbioportal.service.*; import org.cbioportal.service.exception.StudyNotFoundException; @@ -16,11 +17,11 @@ import org.cbioportal.web.config.annotation.InternalApi; import org.cbioportal.model.AlterationFilter; import org.cbioportal.web.parameter.*; -import org.cbioportal.web.parameter.sort.ClinicalDataSortBy; import org.cbioportal.web.util.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -43,7 +44,6 @@ import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; @InternalApi @RestController @@ -85,7 +85,6 @@ private void init() { private StudyViewService studyViewService; @Autowired private ClinicalDataBinUtil clinicalDataBinUtil; - @Autowired private ClinicalEventService clinicalEventService; @@ -181,6 +180,37 @@ public List cachableFetchClinicalDataBinCounts( } @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") + @RequestMapping(value = "/custom-data-bin-counts/fetch", method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @ApiOperation("Fetch custom data bin counts by study view filter") + public ResponseEntity> fetchCustomDataBinCounts( + @ApiParam("Method for data binning") + @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, + @ApiParam(required = true, value = "Clinical data bin count filter") + @Valid @RequestBody(required = false) ClinicalDataBinCountFilter clinicalDataBinCountFilter, + @ApiIgnore // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, + @ApiIgnore // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. + @Valid @RequestAttribute(required = false, value = "interceptedClinicalDataBinCountFilter") ClinicalDataBinCountFilter interceptedClinicalDataBinCountFilter + ) { + // TODO code shared with ClinicalDataController.fetchCustomDataCounts + List attributes = interceptedClinicalDataBinCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = interceptedClinicalDataBinCountFilter.getStudyViewFilter(); + if (attributes.size() == 1) { + studyViewFilterUtil.removeSelfCustomDataFromFilter(attributes.get(0).getAttributeId(), studyViewFilter); + } + List filteredSampleIdentifiers = studyViewFilterApplier.apply(studyViewFilter); + + if (filteredSampleIdentifiers.isEmpty()) { + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); + } + + final List clinicalDataBins = clinicalDataBinUtil.fetchCustomDataBinCounts(dataBinMethod, interceptedClinicalDataBinCountFilter, false); + + return new ResponseEntity<>(clinicalDataBins, HttpStatus.OK); + } + + @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection',T(org.cbioportal.utils.security.AccessLevel).READ)") @RequestMapping(value = "/mutated-genes/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation("Fetch mutated genes by study view filter") @@ -255,7 +285,43 @@ public List cacheableFetchStructuralVariantGenes( } return alterationCountByGenes; } + + @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") + @RequestMapping(value = "/structuralvariant-counts/fetch", method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @ApiOperation("Fetch structural variant genes by study view filter") + public ResponseEntity> fetchStructuralVariantCounts( + @ApiParam(required = true, value = "Study view filter") + @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter, + @ApiIgnore // prevent reference to this attribute in the swagger-ui interface. This attribute is needed for the @PreAuthorize tag above. + @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, + @ApiIgnore // prevent reference to this attribute in the swagger-ui interface. + @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter + ) throws StudyNotFoundException { + boolean singleStudyUnfiltered = studyViewFilterUtil.isSingleStudyUnfiltered(interceptedStudyViewFilter); + List alterationCountByStructuralVariants = + instance.cacheableFetchStructuralVariantCounts(interceptedStudyViewFilter, singleStudyUnfiltered); + return new ResponseEntity<>(alterationCountByStructuralVariants, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled() && #singleStudyUnfiltered" + ) + public List cacheableFetchStructuralVariantCounts( + StudyViewFilter interceptedStudyViewFilter, boolean singleStudyUnfiltered + ) throws StudyNotFoundException { + + List sampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); + if(CollectionUtils.isNotEmpty(sampleIdentifiers)) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + return studyViewService.getStructuralVariantAlterationCounts(studyIds, sampleIds, interceptedStudyViewFilter.getAlterationFilter()); + } + return new ArrayList<>(); + } @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") @RequestMapping(value = "/cna-genes/fetch", method = RequestMethod.POST, @@ -375,6 +441,7 @@ private static double parseValueLinear(ClinicalData c) { @RequestMapping(value = "/clinical-data-density-plot/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation("Fetch clinical data density plot bins by study view filter") + @Validated public ResponseEntity fetchClinicalDataDensityPlot( @ApiParam(required = true, value = "Clinical Attribute ID of the X axis") @RequestParam String xAxisAttributeId, @@ -401,7 +468,7 @@ public ResponseEntity fetchClinicalDataDensityPlot( @ApiIgnore // 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, @ApiParam(required = true, value = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter) { + @RequestBody(required = false) StudyViewFilter studyViewFilter) { List studyIds = new ArrayList<>(); List sampleIds = new ArrayList<>(); @@ -794,6 +861,47 @@ public ResponseEntity> fetchGenomicDataBinCounts( return new ResponseEntity<>(studyViewFilterApplier.getDataBins(dataBinMethod, interceptedGenomicDataBinCountFilter), HttpStatus.OK); } + @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") + @RequestMapping(value = "/genomic-data-counts/fetch", method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @ApiOperation("Fetch genomic data counts by GenomicDataCountFilter") + public ResponseEntity> fetchGenomicDataCounts( + @ApiParam(required = true, value = "Genomic data count filter") @Valid @RequestBody(required = false) GenomicDataCountFilter genomicDataCountFilter, + @ApiIgnore // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, + @ApiParam(required = true, value = "Intercepted Genomic Data Count Filter") + @ApiIgnore + @Valid @RequestAttribute(required = false, value = "interceptedGenomicDataCountFilter") GenomicDataCountFilter interceptedGenomicDataCountFilter + ) throws StudyNotFoundException { + List gdFilters = interceptedGenomicDataCountFilter.getGenomicDataFilters(); + StudyViewFilter studyViewFilter = interceptedGenomicDataCountFilter.getStudyViewFilter(); + // when there is only one filter, it means study view is doing a single chart filter operation + // remove filter from studyViewFilter to return all data counts + // the reason we do this is to make sure after chart get filtered, user can still see unselected portion of the chart + if (gdFilters.size() == 1) { + studyViewFilterUtil.removeSelfFromGenomicDataFilter( + gdFilters.get(0).getHugoGeneSymbol(), + gdFilters.get(0).getProfileType(), + studyViewFilter); + } + List filteredSampleIdentifiers = studyViewFilterApplier.apply(studyViewFilter); + + if (filteredSampleIdentifiers.isEmpty()) { + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); + } + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + + List result = studyViewService.getCNAAlterationCountsByGeneSpecific( + studyIds, + sampleIds, + gdFilters.stream().map(gdFilter -> new Pair<>(gdFilter.getHugoGeneSymbol(), gdFilter.getProfileType())).collect(Collectors.toList())); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") @RequestMapping(value = "/generic-assay-data-counts/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation("Fetch generic assay data counts by study view filter") @@ -853,39 +961,56 @@ public ResponseEntity> fetchGenericAssayDataBinCounts( @ApiOperation("Fetch clinical data for the Clinical Tab of Study View") public ResponseEntity fetchClinicalDataClinicalTable( @ApiParam(required = true, value = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter, + @Valid @RequestBody(required = false) + StudyViewFilter studyViewFilter, @ApiIgnore // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, @ApiIgnore // 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, + @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter, @ApiParam("Page size of the result list") @Max(CLINICAL_TAB_MAX_PAGE_SIZE) @Min(PagingConstants.NO_PAGING_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_NO_PAGING_PAGE_SIZE) Integer pageSize, + @RequestParam(defaultValue = PagingConstants.DEFAULT_NO_PAGING_PAGE_SIZE) + Integer pageSize, @ApiParam("Page number of the result list") @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, @ApiParam("Search term to filter sample rows. Samples are returned " + "with a partial match to the search term for any sample clinical attribute.") - @RequestParam(defaultValue = "") String searchTerm, - @ApiParam("Name of the property that the result list is sorted by") - @RequestParam(required = false) ClinicalDataSortBy sortBy, + @RequestParam(defaultValue = "") + String searchTerm, + @ApiParam(value = "sampleId, patientId, or the ATTR_ID to sorted by") + @RequestParam(required = false) + // TODO: Can we narrow down this string to a specific enum? + String sortBy, @ApiParam("Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) { - + @RequestParam(defaultValue = "ASC") + Direction direction + ) { List sampleStudyIds = new ArrayList<>(); List sampleIds = new ArrayList<>(); List filteredSampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, sampleStudyIds, sampleIds); - List sampleClinicalData = clinicalDataService.fetchSampleClinicalDataClinicalTable( + List sampleClinicalData = clinicalDataService.fetchSampleClinicalTable( sampleStudyIds, sampleIds, pageSize, pageNumber, searchTerm, - sortBy != null ? sortBy.getOriginalValue() : null, - direction.name()); + sortBy, + direction.name() + ); + Integer total = clinicalDataService.fetchSampleClinicalTableCount( + sampleStudyIds, + sampleIds, + searchTerm, + sortBy, + direction.name() + ); // Return empty when possible. if (sampleClinicalData.isEmpty()) { @@ -908,8 +1033,10 @@ public ResponseEntity fetchClinicalDataClinicalTable( final ClinicalDataCollection clinicalDataCollection = new ClinicalDataCollection(); clinicalDataCollection.setSampleClinicalData(sampleClinicalData); clinicalDataCollection.setPatientClinicalData(patientClinicalData); - - return new ResponseEntity<>(clinicalDataCollection, HttpStatus.OK); + + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, total.toString()); + return new ResponseEntity<>(clinicalDataCollection, responseHeaders, HttpStatus.OK); } @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") diff --git a/web/src/main/java/org/cbioportal/web/TreatmentController.java b/web/src/main/java/org/cbioportal/web/TreatmentController.java index f2a933c4616..c17ecda37f2 100644 --- a/web/src/main/java/org/cbioportal/web/TreatmentController.java +++ b/web/src/main/java/org/cbioportal/web/TreatmentController.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Set; @PublicApi @RestController @@ -57,7 +58,7 @@ private void init() { @RequestMapping(value = "/treatments/patient", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation("Get all patient level treatments") public ResponseEntity> getAllPatientTreatments( - @ApiParam(required = false, defaultValue = "Treatment") + @ApiParam(required = false, defaultValue = "Agent") @RequestParam(name = "tier", required = false, defaultValue = "Agent") ClinicalEventKeyCode tier, @@ -101,7 +102,7 @@ public List cachableGetAllPatientTreatments( @RequestMapping(value = "/treatments/sample", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation("Get all sample level treatments") public ResponseEntity> getAllSampleTreatments( - @ApiParam(required = false, defaultValue = "Treatment") + @ApiParam(required = false, defaultValue = "Agent") @RequestParam(name = "tier", required = false, defaultValue = "Agent") ClinicalEventKeyCode tier, @@ -144,33 +145,44 @@ public List cacheableGetAllSampleTreatments( @RequestMapping(value = "/treatments/display-patient", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation("Should patient level treatments be displayed") public ResponseEntity getContainsTreatmentData( - @ApiParam(required = false, defaultValue = "Treatment") + @ApiParam(required = false, defaultValue = "Agent") @RequestParam(name = "tier", required = false, defaultValue = "Agent") ClinicalEventKeyCode tier, @ApiParam(required = true, value = "List of Study IDs") @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) @RequestBody - List studyIds + Set studyIds ) { - Boolean containsTreatmentData = treatmentService.containsTreatmentData(studyIds, tier); + Boolean containsTreatmentData = instance.cacheableGetContainsTreatmentData(studyIds, tier); return new ResponseEntity<>(containsTreatmentData, HttpStatus.OK); } + // Caching enabled for any number of studies as the requests contains only studyIds and the response is a boolean + @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") + public Boolean cacheableGetContainsTreatmentData(Set studyIds, ClinicalEventKeyCode tier) { + return treatmentService.containsTreatmentData(new ArrayList<>(studyIds), tier); + } + @PreAuthorize("hasPermission(#studyIds, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") @RequestMapping(value = "/treatments/display-sample", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation("Should sample level treatments be displayed") public ResponseEntity getContainsSampleTreatmentData( - @ApiParam(required = false, defaultValue = "Treatment") + @ApiParam(required = false, defaultValue = "Agent") @RequestParam(name = "tier", required = false, defaultValue = "Agent") ClinicalEventKeyCode tier, @ApiParam(required = true, value = "List of Study IDs") @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) @RequestBody - List studyIds + Set studyIds ) { - Boolean containsTreatmentData = treatmentService.containsSampleTreatmentData(studyIds, tier); + Boolean containsTreatmentData = instance.cacheableGetContainsSampleTreatmentData(studyIds, tier); return new ResponseEntity<>(containsTreatmentData, HttpStatus.OK); } + + @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") + public Boolean cacheableGetContainsSampleTreatmentData(Set studyIds, ClinicalEventKeyCode tier) { + return treatmentService.containsSampleTreatmentData(new ArrayList<>(studyIds), tier); + } } diff --git a/web/src/main/java/org/cbioportal/web/config/CustomObjectMapper.java b/web/src/main/java/org/cbioportal/web/config/CustomObjectMapper.java index ed80696367b..740a73dbb81 100644 --- a/web/src/main/java/org/cbioportal/web/config/CustomObjectMapper.java +++ b/web/src/main/java/org/cbioportal/web/config/CustomObjectMapper.java @@ -98,13 +98,13 @@ import org.cbioportal.web.mixin.SessionMixin; import org.cbioportal.web.mixin.StructuralVariantMixin; import org.cbioportal.web.mixin.TypeOfCancerMixin; -import org.cbioportal.web.parameter.CustomDataSession; +import org.cbioportal.service.util.CustomDataSession; import org.cbioportal.web.parameter.PageSettings; import org.cbioportal.web.parameter.PageSettingsData; import org.cbioportal.web.parameter.StudyPageSettings; import org.cbioportal.web.parameter.VirtualStudy; import org.cbioportal.web.parameter.VirtualStudyData; -import org.cbioportal.web.CustomAttributeWithData; +import org.cbioportal.service.util.CustomAttributeWithData; public class CustomObjectMapper extends ObjectMapper { diff --git a/web/src/main/java/org/cbioportal/web/config/WebServletContextListener.java b/web/src/main/java/org/cbioportal/web/config/WebServletContextListener.java index e1d11d3749f..d4a2b8eb4ce 100644 --- a/web/src/main/java/org/cbioportal/web/config/WebServletContextListener.java +++ b/web/src/main/java/org/cbioportal/web/config/WebServletContextListener.java @@ -47,12 +47,12 @@ public void afterPropertiesSet() throws Exception { private void checkOncokbInfo() { if(StringUtils.isEmpty(this.oncokbToken) && (StringUtils.isEmpty(this.oncokbURL) || this.oncokbURL.equalsIgnoreCase(DEFAULT_ONCOKB_URL))) { - System.out.println("----------------------------------------------------------------------------------------------------------------"); + System.out.println("\n----------------------------------------------------------------------------------------------------------------"); // oncokb.org is deprecated, www.oncokb.org should be used System.out.println("-- You are connecting to the OncoKB public instance which does not include any therapeutic information."); System.out.println("-- Please consider obtaining a license to support future OncoKB development by following https://docs.cbioportal.org/2.4-integration-with-other-webservices/oncokb-data-access."); System.out.println("-- Thank you."); - System.out.println("----------------------------------------------------------------------------------------------------------------"); + System.out.println("----------------------------------------------------------------------------------------------------------------\n"); } } diff --git a/web/src/main/java/org/cbioportal/web/mixin/MutationMixin.java b/web/src/main/java/org/cbioportal/web/mixin/MutationMixin.java index 7cee18693fe..86b80142466 100644 --- a/web/src/main/java/org/cbioportal/web/mixin/MutationMixin.java +++ b/web/src/main/java/org/cbioportal/web/mixin/MutationMixin.java @@ -7,11 +7,11 @@ public class MutationMixin { @JsonProperty("variantAllele") private String tumorSeqAllele; @JsonProperty("refseqMrnaId") - private String oncotatorRefseqMrnaId; + private String refseqMrnaId; @JsonProperty("proteinPosStart") - private Integer oncotatorProteinPosStart; + private Integer proteinPosStart; @JsonProperty("proteinPosEnd") - private Integer oncotatorProteinPosEnd; + private Integer proteinPosEnd; @JsonProperty("chr") private String chr; @JsonProperty("namespaceColumns") diff --git a/web/src/main/java/org/cbioportal/web/parameter/DataBinMethod.java b/web/src/main/java/org/cbioportal/web/parameter/DataBinMethod.java index 7d0d8989cf2..c63dda3c48c 100644 --- a/web/src/main/java/org/cbioportal/web/parameter/DataBinMethod.java +++ b/web/src/main/java/org/cbioportal/web/parameter/DataBinMethod.java @@ -1,7 +1,19 @@ package org.cbioportal.web.parameter; +/** + * STATIC and DYNAMIC binning relate to the way bin boundaries are derived from numerical data of a sample cohort + * defined by a Study View Filter (SVF). + * + * When binning in STATIC mode, the binning ignores any filter in the SVF on the attribute that is the subject of + * binning. In effect, it bins all values of the cohort. This mode is important to drive frontend behavior where + * histograms show bins related to the entire data range, but highlight the currently selected/filtered data in blue + * (non-selected data bins in grey). In effect, this way the non-selected data influences the boundaries of the data + * bins, irrespective of the selected attribute range. + * + * When binning in DYNAMIC mode, only the attribute data is binned that is defined by the SVF. The non-selected + * rest of the data does not influence the bin boundaries. + */ public enum DataBinMethod { - STATIC, DYNAMIC } diff --git a/web/src/main/java/org/cbioportal/web/parameter/GenomicDataCountFilter.java b/web/src/main/java/org/cbioportal/web/parameter/GenomicDataCountFilter.java new file mode 100644 index 00000000000..c01ec7696c1 --- /dev/null +++ b/web/src/main/java/org/cbioportal/web/parameter/GenomicDataCountFilter.java @@ -0,0 +1,26 @@ +package org.cbioportal.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class GenomicDataCountFilter implements Serializable { + + private List genomicDataFilters; + private StudyViewFilter studyViewFilter; + + public List getGenomicDataFilters() { + return genomicDataFilters; + } + + public void setGenomicDataFilters(List genomicDataFilters) { + this.genomicDataFilters = genomicDataFilters; + } + + public StudyViewFilter getStudyViewFilter() { + return studyViewFilter; + } + + public void setStudyViewFilter(StudyViewFilter studyViewFilter) { + this.studyViewFilter = studyViewFilter; + } +} diff --git a/web/src/main/java/org/cbioportal/web/parameter/StudyViewFilter.java b/web/src/main/java/org/cbioportal/web/parameter/StudyViewFilter.java index b69b829e307..6a9e8c9b5a0 100644 --- a/web/src/main/java/org/cbioportal/web/parameter/StudyViewFilter.java +++ b/web/src/main/java/org/cbioportal/web/parameter/StudyViewFilter.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Objects; +import javax.validation.Valid; import javax.validation.constraints.AssertTrue; import javax.validation.constraints.Size; @@ -12,6 +13,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.cbioportal.model.AlterationFilter; import org.cbioportal.model.GeneFilter; +import org.cbioportal.model.StudyViewStructuralVariantFilter; import org.cbioportal.web.parameter.filter.*; @JsonIgnoreProperties(ignoreUnknown = true) @@ -24,6 +26,8 @@ public class StudyViewFilter implements Serializable { private List studyIds; private List clinicalDataFilters; private List geneFilters; + @Valid + private List structuralVariantFilters; private AndedSampleTreatmentFilters sampleTreatmentFilters; private AndedSampleTreatmentFilters sampleTreatmentGroupFilters; private AndedSampleTreatmentFilters sampleTreatmentTargetFilters; @@ -110,6 +114,14 @@ public void setGeneFilters(List geneFilters) { this.geneFilters = geneFilters; } + public List getStructuralVariantFilters() { + return structuralVariantFilters; + } + + public void setStructuralVariantFilters(List structuralVariantFilters) { + this.structuralVariantFilters = structuralVariantFilters; + } + public List> getGenomicProfiles() { return genomicProfiles; } diff --git a/web/src/main/java/org/cbioportal/web/parameter/sort/MutationSortBy.java b/web/src/main/java/org/cbioportal/web/parameter/sort/MutationSortBy.java index ff89f1960f8..ce2caf51cdb 100644 --- a/web/src/main/java/org/cbioportal/web/parameter/sort/MutationSortBy.java +++ b/web/src/main/java/org/cbioportal/web/parameter/sort/MutationSortBy.java @@ -19,9 +19,9 @@ public enum MutationSortBy { mutationType("mutationType"), ncbiBuild("ncbiBuild"), variantType("variantType"), - refseqMrnaId("oncotatorRefseqMrnaId"), - proteinPosStart("oncotatorProteinPosStart"), - proteinPosEnd("oncotatorProteinPosEnd"), + refseqMrnaId("refseqMrnaId"), + proteinPosStart("proteinPosStart"), + proteinPosEnd("proteinPosEnd"), keyword("keyword"); private String originalValue; diff --git a/web/src/main/java/org/cbioportal/web/studyview/CustomDataController.java b/web/src/main/java/org/cbioportal/web/studyview/CustomDataController.java index b0dfc8c0394..85e14eb5baa 100644 --- a/web/src/main/java/org/cbioportal/web/studyview/CustomDataController.java +++ b/web/src/main/java/org/cbioportal/web/studyview/CustomDataController.java @@ -4,8 +4,6 @@ import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; import java.util.function.Function; import java.util.stream.Collectors; @@ -13,15 +11,14 @@ import org.cbioportal.model.ClinicalDataCountItem; import org.cbioportal.model.Patient; +import org.cbioportal.service.CustomDataService; import org.cbioportal.service.PatientService; -import org.cbioportal.session_service.domain.SessionType; import org.cbioportal.web.config.annotation.InternalApi; import org.cbioportal.web.parameter.ClinicalDataCountFilter; import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.cbioportal.web.parameter.CustomDataSession; +import org.cbioportal.service.util.CustomDataSession; import org.cbioportal.web.parameter.SampleIdentifier; import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.SessionServiceRequestHandler; import org.cbioportal.web.util.StudyViewFilterApplier; import org.cbioportal.web.util.StudyViewFilterUtil; import org.springframework.beans.factory.annotation.Autowired; @@ -52,7 +49,7 @@ public class CustomDataController { @Autowired private StudyViewFilterUtil studyViewFilterUtil; @Autowired - private SessionServiceRequestHandler sessionServiceRequestHandler; + private CustomDataService customDataService; @Autowired private PatientService patientService; @@ -80,43 +77,27 @@ public ResponseEntity> fetchCustomDataCounts( return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); } - List> postFutures = attributes.stream().map(clinicalDataFilter -> { - return CompletableFuture.supplyAsync(() -> { - try { - return (CustomDataSession) sessionServiceRequestHandler.getSession(SessionType.custom_data, - clinicalDataFilter.getAttributeId()); - } catch (Exception e) { - return null; - } - }); - }).collect(Collectors.toList()); - - CompletableFuture.allOf(postFutures.toArray(new CompletableFuture[postFutures.size()])).join(); - - List customDataSessions = postFutures - .stream() - .map(CompletableFuture::join) - .filter(Objects::nonNull) - .collect(Collectors.toList()); + final List attributeIds = attributes.stream().map(ClinicalDataFilter::getAttributeId).collect(Collectors.toList()); + Map customDataSessionsMap = customDataService.getCustomDataSessions(attributeIds); Map filteredSamplesMap = filteredSampleIdentifiers.stream() - .collect(Collectors.toMap(sampleIdentifier -> { - return studyViewFilterUtil.getCaseUniqueKey(sampleIdentifier.getStudyId(), - sampleIdentifier.getSampleId()); - }, Function.identity())); + .collect(Collectors.toMap(sampleIdentifier -> studyViewFilterUtil.getCaseUniqueKey( + sampleIdentifier.getStudyId(), + sampleIdentifier.getSampleId() + ), Function.identity())); List studyIds = new ArrayList<>(); List sampleIds = new ArrayList<>(); studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); - long patientCustomDataSessionsCount = customDataSessions.stream() + long patientCustomDataSessionsCount = customDataSessionsMap.values().stream() .filter(customDataSession -> customDataSession.getData().getPatientAttribute()).count(); - List patients = new ArrayList(); + List patients = new ArrayList<>(); if (patientCustomDataSessionsCount > 0) { patients.addAll(patientService.getPatientsOfSamples(studyIds, sampleIds)); } - List result = studyViewFilterUtil.getClinicalDataCountsFromCustomData(customDataSessions, + List result = studyViewFilterUtil.getClinicalDataCountsFromCustomData(customDataSessionsMap.values(), filteredSamplesMap, patients); return new ResponseEntity<>(result, HttpStatus.OK); diff --git a/web/src/main/java/org/cbioportal/web/util/BinningData.java b/web/src/main/java/org/cbioportal/web/util/BinningData.java new file mode 100644 index 00000000000..82edafd1edd --- /dev/null +++ b/web/src/main/java/org/cbioportal/web/util/BinningData.java @@ -0,0 +1,39 @@ +package org.cbioportal.web.util; + +import com.google.common.collect.ImmutableList; +import org.cbioportal.model.Binnable; +import org.cbioportal.model.ClinicalData; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.util.Collections.unmodifiableList; + +public class BinningData { + public final List samples; + public final List patients; + public final List conflictingPatientAttributes; + private final List allData; + + public BinningData( + List samples, + List patients, + List conflictingPatientAttributes + ) { + this.samples = unmodifiableList(samples); + this.patients = unmodifiableList(patients); + this.conflictingPatientAttributes = unmodifiableList(conflictingPatientAttributes); + this.allData = Stream.of( + this.samples, + this.patients, + this.conflictingPatientAttributes + ).flatMap(Collection::stream).collect(Collectors.toList()); + } + + public List getAllData() { + return allData; + } + +} \ No newline at end of file diff --git a/web/src/main/java/org/cbioportal/web/util/BinningIds.java b/web/src/main/java/org/cbioportal/web/util/BinningIds.java new file mode 100644 index 00000000000..6d19d79051b --- /dev/null +++ b/web/src/main/java/org/cbioportal/web/util/BinningIds.java @@ -0,0 +1,75 @@ +package org.cbioportal.web.util; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Collections.unmodifiableList; + +/** + * All IDs relevant for binning of clinical (and custom clinical) data + */ +public class BinningIds { + private List studyIds = new ArrayList<>(); + private List sampleIds = new ArrayList<>(); + private List patientIds = new ArrayList<>(); + private List studyIdsOfPatients = new ArrayList<>(); + private List uniqueSampleKeys = new ArrayList<>(); + private List uniquePatientKeys = new ArrayList<>(); + private List sampleAttributeIds = new ArrayList<>(); + private List patientAttributeIds = new ArrayList<>(); + private List conflictingPatientAttributeIds = new ArrayList<>(); + + public BinningIds() {} + + /** + * Create shallow clone + */ + public BinningIds(BinningIds toClone) { + this(); + this.studyIds = new ArrayList<>(toClone.getStudyIds()); + this.sampleIds = new ArrayList<>(toClone.getSampleIds()); + this.patientIds = new ArrayList<>(toClone.getPatientIds()); + this.studyIdsOfPatients = new ArrayList<>(toClone.getStudyIdsOfPatients()); + this.uniqueSampleKeys = new ArrayList<>(toClone.getUniqueSampleKeys()); + this.uniquePatientKeys = new ArrayList<>(toClone.getUniquePatientKeys()); + this.sampleAttributeIds = new ArrayList<>(toClone.getSampleAttributeIds()); + this.patientAttributeIds = new ArrayList<>(toClone.getPatientAttributeIds()); + this.conflictingPatientAttributeIds = new ArrayList<>(toClone.getConflictingPatientAttributeIds()); + } + + public List getStudyIds() { + return studyIds; + } + + public List getSampleIds() { + return sampleIds; + } + + public List getPatientIds() { + return patientIds; + } + + public List getStudyIdsOfPatients() { + return studyIdsOfPatients; + } + + public List getUniqueSampleKeys() { + return uniqueSampleKeys; + } + + public List getUniquePatientKeys() { + return uniquePatientKeys; + } + + public List getSampleAttributeIds() { + return sampleAttributeIds; + } + + public List getPatientAttributeIds() { + return patientAttributeIds; + } + + public List getConflictingPatientAttributeIds() { + return conflictingPatientAttributeIds; + } +} \ No newline at end of file diff --git a/web/src/main/java/org/cbioportal/web/util/ClinicalDataBinUtil.java b/web/src/main/java/org/cbioportal/web/util/ClinicalDataBinUtil.java index 1daaecac7e8..7928dccaa49 100644 --- a/web/src/main/java/org/cbioportal/web/util/ClinicalDataBinUtil.java +++ b/web/src/main/java/org/cbioportal/web/util/ClinicalDataBinUtil.java @@ -1,22 +1,32 @@ package org.cbioportal.web.util; +import org.cbioportal.model.Binnable; import org.cbioportal.model.ClinicalAttribute; import org.cbioportal.model.ClinicalData; import org.cbioportal.model.ClinicalDataBin; -import org.cbioportal.service.ClinicalAttributeService; -import org.cbioportal.service.PatientService; -import org.cbioportal.service.util.ClinicalAttributeUtil; +import org.cbioportal.service.AttributeByStudyService; +import org.cbioportal.service.CustomDataService; +import org.cbioportal.service.util.BinnableCustomDataValue; +import org.cbioportal.service.util.CustomAttributeWithData; +import org.cbioportal.service.util.CustomDataSession; +import org.cbioportal.service.util.CustomDataValue; import org.cbioportal.web.parameter.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; + +import static java.util.Collections.emptyList; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; @Component public class ClinicalDataBinUtil { + @Autowired + private AttributeByStudyService clinicalAttributeService; @Autowired private StudyViewFilterApplier studyViewFilterApplier; @Autowired @@ -26,12 +36,10 @@ public class ClinicalDataBinUtil { @Autowired private StudyViewFilterUtil studyViewFilterUtil; @Autowired - private ClinicalAttributeService clinicalAttributeService; + private CustomDataService customDataService; @Autowired - private ClinicalAttributeUtil clinicalAttributeUtil; - @Autowired - private PatientService patientService; - + private IdPopulator idPopulator; + public StudyViewFilter removeSelfFromFilter(ClinicalDataBinCountFilter dataBinCountFilter) { List attributes = dataBinCountFilter.getAttributes(); StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); @@ -39,7 +47,7 @@ public StudyViewFilter removeSelfFromFilter(ClinicalDataBinCountFilter dataBinCo if (attributes.size() == 1) { studyViewFilterUtil.removeSelfFromFilter(attributes.get(0).getAttributeId(), studyViewFilter); } - + return studyViewFilter; } @@ -48,230 +56,261 @@ public List fetchClinicalDataBinCounts( ClinicalDataBinCountFilter dataBinCountFilter ) { return this.fetchClinicalDataBinCounts( - dataBinMethod, - dataBinCountFilter, + dataBinMethod, + dataBinCountFilter, // by default call the method to remove self from filter true ); } - + public List fetchClinicalDataBinCounts( DataBinMethod dataBinMethod, ClinicalDataBinCountFilter dataBinCountFilter, boolean shouldRemoveSelfFromFilter ) { - List attributes = dataBinCountFilter.getAttributes(); - StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); + StudyViewFilter studyViewFilter = toStudyViewFilter(dataBinCountFilter, shouldRemoveSelfFromFilter); + List unfilteredSamples = filterByStudyAndSample(studyViewFilter); + List attributeIds = toAttributeIds(dataBinCountFilter.getAttributes()); + List clinicalAttributes = fetchClinicalAttributes(attributeIds, unfilteredSamples); + BinningIds binningIds = idPopulator.populateIdLists(unfilteredSamples, clinicalAttributes); + Map attributeByDatatype = toAttributeDatatypeMap(binningIds); + BinningData unfilteredData = (BinningData) (BinningData) fetchBinningData(binningIds); + return createBins( + dataBinMethod, + dataBinCountFilter, + studyViewFilter, + attributeByDatatype, + clinicalAttributes, + binningIds, + unfilteredSamples, + unfilteredData + ); + } - if (shouldRemoveSelfFromFilter) { - studyViewFilter = removeSelfFromFilter(dataBinCountFilter); + public List fetchCustomDataBinCounts( + DataBinMethod dataBinMethod, + ClinicalDataBinCountFilter dataBinCountFilter, + boolean shouldRemoveSelfFromFilter + ) { + List attributeIds = toAttributeIds(dataBinCountFilter.getAttributes()); + Map customDataSessions = customDataService.getCustomDataSessions(attributeIds); + Map> customDataByAttributeId = createCustomDataByAttributeId(customDataSessions); + Map customAttributeByDatatype = createCustomAttributeDatatypeMap(customDataSessions); + + StudyViewFilter studyViewFilter = toStudyViewFilter(dataBinCountFilter, shouldRemoveSelfFromFilter); + List unfilteredSamples = filterByStudyAndSample(studyViewFilter); + List customDataAttributes = toCustomAttributes(customDataSessions); + + BinningIds unfilteredIds = idPopulator.populateIdLists(unfilteredSamples, customDataAttributes); + BinningData unfilteredData = fetchCustomBinningData(customDataByAttributeId, unfilteredIds); + + return createBins( + dataBinMethod, + dataBinCountFilter, + studyViewFilter, + customAttributeByDatatype, + customDataAttributes, + unfilteredIds, + unfilteredSamples, + unfilteredData + ); + } + + private List createBins( + DataBinMethod dataBinMethod, + ClinicalDataBinCountFilter dataBinCountFilter, + StudyViewFilter studyViewFilter, + Map clinicalDataAttributeDatatypeMap, + List clinicalAttributes, + BinningIds unfilteredIds, + List unfilteredSampleIds, + BinningData unfilteredData + ) { + List filteredSampleIds = filterSampleIds(studyViewFilter, unfilteredSampleIds); + + BinningIds filteredIds; + List filteredClinicalData; + if (filteredSampleIds.equals(unfilteredSampleIds)) { + // if filtered and unfiltered samples are exactly the same, no need to fetch clinical data again: + filteredIds = new BinningIds(unfilteredIds); + filteredClinicalData = unfilteredData.getAllData(); + } else { + filteredIds = idPopulator.populateIdLists(filteredSampleIds, clinicalAttributes); + filteredClinicalData = filterClinicalData(unfilteredData, filteredIds); } - List attributeIds = attributes.stream().map(ClinicalDataBinFilter::getAttributeId).collect(Collectors.toList()); - - // filter only by study id and sample identifiers, ignore rest - List unfilteredSampleIdentifiers = filterByStudyAndSample(studyViewFilter); - - List unfilteredStudyIds = new ArrayList<>(); - List unfilteredSampleIds = new ArrayList<>(); - List unfilteredPatientIds = new ArrayList<>(); - List studyIdsOfUnfilteredPatients = new ArrayList<>(); - List unfilteredUniqueSampleKeys = new ArrayList<>(); - List unfilteredUniquePatientKeys = new ArrayList<>(); - List unfilteredSampleAttributeIds = new ArrayList<>(); - List unfilteredPatientAttributeIds = new ArrayList<>(); - // patient attributes which are also sample attributes in other studies - List unfilteredConflictingPatientAttributeIds = new ArrayList<>(); - - populateIdLists( - // input - unfilteredSampleIdentifiers, - attributeIds, - - // output - unfilteredStudyIds, - unfilteredSampleIds, - unfilteredPatientIds, - studyIdsOfUnfilteredPatients, - unfilteredUniqueSampleKeys, - unfilteredUniquePatientKeys, - unfilteredSampleAttributeIds, - unfilteredPatientAttributeIds, - unfilteredConflictingPatientAttributeIds - ); + List attributes = dataBinCountFilter.getAttributes(); + if (dataBinMethod == DataBinMethod.STATIC) { + if (unfilteredSampleIds.isEmpty() || unfilteredData.getAllData().isEmpty()) { + return emptyList(); + } + return calculateStaticDataBins( + attributes, + clinicalDataAttributeDatatypeMap, + toClinicalDataByAttributeId(unfilteredData.getAllData()), + toClinicalDataByAttributeId(filteredClinicalData), + unfilteredIds.getUniqueSampleKeys(), + unfilteredIds.getUniquePatientKeys(), + filteredIds.getUniqueSampleKeys(), + filteredIds.getUniquePatientKeys() + ); + } else { // dataBinMethod == DataBinMethod.DYNAMIC + if (filteredClinicalData.isEmpty()) { + return emptyList(); + } + return calculateDynamicDataBins( + attributes, + clinicalDataAttributeDatatypeMap, + toClinicalDataByAttributeId(filteredClinicalData), + filteredIds.getUniqueSampleKeys(), + filteredIds.getUniquePatientKeys() + ); + } + } - Map attributeDatatypeMap = constructAttributeDataMap( - unfilteredSampleAttributeIds, - unfilteredPatientAttributeIds, - unfilteredConflictingPatientAttributeIds - ); + private List toCustomAttributes( + Map customDataSessions + ) { + return customDataSessions + .entrySet() + .stream() + .map(e -> toClinicalAttribute(e.getKey(), e.getValue().getData())) + .collect(toList()); + } - List unfilteredClinicalDataForSamples = clinicalDataFetcher.fetchClinicalDataForSamples( - unfilteredStudyIds, - unfilteredSampleIds, - new ArrayList<>(unfilteredSampleAttributeIds) - ); + private ClinicalAttribute toClinicalAttribute(String key, CustomAttributeWithData data) { + ClinicalAttribute result = new ClinicalAttribute(); + result.setPatientAttribute(data.getPatientAttribute()); + result.setAttrId(key); + result.setDatatype(data.getDatatype()); + return result; + } - List unfilteredClinicalDataForPatients = clinicalDataFetcher.fetchClinicalDataForPatients( - studyIdsOfUnfilteredPatients, - unfilteredPatientIds, - new ArrayList<>(unfilteredPatientAttributeIds) - ); + private Map> toClinicalDataByAttributeId(List unfilteredData) { + return unfilteredData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + } - List unfilteredClinicalDataForConflictingPatientAttributes = clinicalDataFetcher.fetchClinicalDataForConflictingPatientAttributes( - studyIdsOfUnfilteredPatients, - unfilteredPatientIds, - new ArrayList<>(unfilteredConflictingPatientAttributeIds) + private List filterClinicalData( + BinningData unfilteredData, + BinningIds filteredIds + ) { + return studyViewFilterUtil.filterClinicalData( + unfilteredData.samples, + unfilteredData.patients, + unfilteredData.conflictingPatientAttributes, + filteredIds.getStudyIds(), + filteredIds.getSampleIds(), + filteredIds.getStudyIdsOfPatients(), + filteredIds.getPatientIds(), + filteredIds.getSampleAttributeIds(), + filteredIds.getPatientAttributeIds(), + filteredIds.getConflictingPatientAttributeIds() ); + } - List unfilteredClinicalData = Stream.of( - unfilteredClinicalDataForSamples, - unfilteredClinicalDataForPatients, - unfilteredClinicalDataForConflictingPatientAttributes - ).flatMap(Collection::stream).collect(Collectors.toList()); - - // if filters are practically the same no need to re-apply them - List filteredSampleIdentifiers = - studyViewFilterUtil.shouldSkipFilterForClinicalDataBins(studyViewFilter) ? - unfilteredSampleIdentifiers : studyViewFilterApplier.apply(studyViewFilter); - - List filteredUniqueSampleKeys; - List filteredUniquePatientKeys; - List filteredClinicalData; - - // if filtered and unfiltered samples are exactly the same, no need to fetch clinical data again - if (filteredSampleIdentifiers.equals(unfilteredSampleIdentifiers)) { - filteredUniqueSampleKeys = unfilteredUniqueSampleKeys; - filteredUniquePatientKeys = unfilteredUniquePatientKeys; - filteredClinicalData = unfilteredClinicalData; - } - else { - List filteredStudyIds = new ArrayList<>(); - List filteredSampleIds = new ArrayList<>(); - List filteredPatientIds = new ArrayList<>(); - List studyIdsOfFilteredPatients = new ArrayList<>(); - filteredUniqueSampleKeys = new ArrayList<>(); - filteredUniquePatientKeys = new ArrayList<>(); - List filteredSampleAttributeIds = new ArrayList<>(); - List filteredPatientAttributeIds = new ArrayList<>(); - // patient attributes which are also sample attributes in other studies - List filteredConflictingPatientAttributeIds = new ArrayList<>(); - - populateIdLists( - // input - filteredSampleIdentifiers, - attributeIds, - - // output - filteredStudyIds, - filteredSampleIds, - filteredPatientIds, - studyIdsOfFilteredPatients, - filteredUniqueSampleKeys, - filteredUniquePatientKeys, - filteredSampleAttributeIds, - filteredPatientAttributeIds, - filteredConflictingPatientAttributeIds - ); + private List filterSampleIds(StudyViewFilter studyViewFilter, List unfilteredSampleIds) { + return studyViewFilterUtil.shouldSkipFilterForClinicalDataBins(studyViewFilter) + ? unfilteredSampleIds + : studyViewFilterApplier.apply(studyViewFilter); + } - filteredClinicalData = studyViewFilterUtil.filterClinicalData( - unfilteredClinicalDataForSamples, - unfilteredClinicalDataForPatients, - unfilteredClinicalDataForConflictingPatientAttributes, - filteredStudyIds, - filteredSampleIds, - studyIdsOfFilteredPatients, - filteredPatientIds, - filteredSampleAttributeIds, - filteredPatientAttributeIds, - filteredConflictingPatientAttributeIds - ); + private List toAttributeIds(List dataBinCountFilter) { + return dataBinCountFilter.stream() + .map(ClinicalDataBinFilter::getAttributeId).collect(toList()); + } + + private StudyViewFilter toStudyViewFilter(ClinicalDataBinCountFilter dataBinCountFilter, boolean shouldRemoveSelfFromFilter) { + StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); + + if (shouldRemoveSelfFromFilter) { + studyViewFilter = removeSelfFromFilter(dataBinCountFilter); } + return studyViewFilter; + } - Map> unfilteredClinicalDataByAttributeId = - unfilteredClinicalData.stream().collect(Collectors.groupingBy(ClinicalData::getAttrId)); + private Map> createCustomDataByAttributeId(Map customDataSessions) { + return customDataSessions.entrySet().stream() + .collect(toMap( + Map.Entry::getKey, + entry -> entry + .getValue() + .getData() + .getData() + .stream() + .map(mapCustomToBinnable(entry)) + .collect(toList()) + )); + } - Map> filteredClinicalDataByAttributeId = - filteredClinicalData.stream().collect(Collectors.groupingBy(ClinicalData::getAttrId)); + private BinningData fetchBinningData(BinningIds binningIds) { + List samples = clinicalDataFetcher.fetchClinicalDataForSamples( + binningIds.getStudyIds(), + binningIds.getSampleIds(), + binningIds.getSampleAttributeIds() + ); - List clinicalDataBins = Collections.emptyList(); + List patients = clinicalDataFetcher.fetchClinicalDataForPatients( + binningIds.getStudyIdsOfPatients(), + binningIds.getPatientIds(), + binningIds.getPatientAttributeIds() + ); - if (dataBinMethod == DataBinMethod.STATIC) { - if (!unfilteredSampleIdentifiers.isEmpty() && !unfilteredClinicalData.isEmpty()) { - clinicalDataBins = calculateStaticDataBins( - attributes, - attributeDatatypeMap, - unfilteredClinicalDataByAttributeId, - filteredClinicalDataByAttributeId, - unfilteredUniqueSampleKeys, - unfilteredUniquePatientKeys, - filteredUniqueSampleKeys, - filteredUniquePatientKeys - ); - } - } - else { // dataBinMethod == DataBinMethod.DYNAMIC - if (!filteredClinicalData.isEmpty()) { - clinicalDataBins = calculateDynamicDataBins( - attributes, - attributeDatatypeMap, - filteredClinicalDataByAttributeId, - filteredUniqueSampleKeys, - filteredUniquePatientKeys - ); - } - } - - return clinicalDataBins; + List conflictingPatientAttributes = clinicalDataFetcher.fetchClinicalDataForConflictingPatientAttributes( + binningIds.getStudyIdsOfPatients(), + binningIds.getPatientIds(), + binningIds.getConflictingPatientAttributeIds() + ); + return new BinningData<>(samples, patients, conflictingPatientAttributes); } - public void populateIdLists( - // input lists - List sampleIdentifiers, - List attributeIds, - // lists to get populated - List studyIds, - List sampleIds, - List patientIds, - List studyIdsOfPatients, - List uniqueSampleKeys, - List uniquePatientKeys, - List sampleAttributeIds, - List patientAttributeIds, - List conflictingPatientAttributeIds + private BinningData fetchCustomBinningData( + Map> clinicalDataByAttributeId, + BinningIds binningIds ) { - studyViewFilterUtil.extractStudyAndSampleIds( - sampleIdentifiers, - studyIds, - sampleIds - ); - - patientService.getPatientsOfSamples(studyIds, sampleIds).stream().forEach(patient -> { - patientIds.add(patient.getStableId()); - studyIdsOfPatients.add(patient.getCancerStudyIdentifier()); - }); + List clinicalDataForPatients = clinicalDataByAttributeId + .values() + .stream() + .filter(e -> e.get(0).isPatientAttribute()) + .flatMap(List::stream) + .collect(toList()); + + List clinicalDataForSamples = clinicalDataByAttributeId + .values() + .stream() + .filter(e -> !e.get(0).isPatientAttribute()) + .flatMap(List::stream) + .collect(toList()); - uniqueSampleKeys.addAll(studyViewFilterApplier.getUniqkeyKeys(studyIds, sampleIds)); - uniquePatientKeys.addAll(studyViewFilterApplier.getUniqkeyKeys(studyIdsOfPatients, patientIds)); + List unfilteredClinicalDataForConflictingPatientAttributes = clinicalDataFetcher.fetchClinicalDataForConflictingPatientAttributes( + binningIds.getStudyIdsOfPatients(), + binningIds.getPatientIds(), + binningIds.getConflictingPatientAttributeIds() + ); + return new BinningData<>( + clinicalDataForSamples, + clinicalDataForPatients, + (List) (List) unfilteredClinicalDataForConflictingPatientAttributes + ); + } - if (attributeIds != null) { - List clinicalAttributes = clinicalAttributeService - .getClinicalAttributesByStudyIdsAndAttributeIds(studyIds, attributeIds); - clinicalAttributeUtil.extractCategorizedClinicalAttributes( - clinicalAttributes, - sampleAttributeIds, - patientAttributeIds, - conflictingPatientAttributeIds + private Function mapCustomToBinnable(Map.Entry entry) { + return customDataValue -> { + final String attributeId = entry.getKey(); + final Boolean patientAttribute = entry.getValue().getData().getPatientAttribute(); + return new BinnableCustomDataValue( + customDataValue, + attributeId, + patientAttribute ); - } + }; } public List calculateStaticDataBins( - List attributes, + List attributes, Map attributeDatatypeMap, - Map> unfilteredClinicalDataByAttributeId, - Map> filteredClinicalDataByAttributeId, + Map> unfilteredClinicalDataByAttributeId, + Map> filteredClinicalDataByAttributeId, List unfilteredUniqueSampleKeys, List unfilteredUniquePatientKeys, List filteredUniqueSampleKeys, @@ -291,13 +330,13 @@ public List calculateStaticDataBins( List dataBins = dataBinner .calculateClinicalDataBins(attribute, clinicalDataType, filteredClinicalDataByAttributeId.getOrDefault(attribute.getAttributeId(), - Collections.emptyList()), + emptyList()), unfilteredClinicalDataByAttributeId.getOrDefault(attribute.getAttributeId(), - Collections.emptyList()), + emptyList()), filteredIds, unfilteredIds) .stream() .map(dataBin -> studyViewFilterUtil.dataBinToClinicalDataBin(attribute, dataBin)) - .collect(Collectors.toList()); + .collect(toList()); clinicalDataBins.addAll(dataBins); } @@ -309,7 +348,7 @@ public List calculateStaticDataBins( public List calculateDynamicDataBins( List attributes, Map attributeDatatypeMap, - Map> filteredClinicalDataByAttributeId, + Map> filteredClinicalDataByAttributeId, List filteredUniqueSampleKeys, List filteredUniquePatientKeys ) { @@ -317,6 +356,7 @@ public List calculateDynamicDataBins( for (ClinicalDataBinFilter attribute : attributes) { + // if there is clinical data for requested attribute if (attributeDatatypeMap.containsKey(attribute.getAttributeId())) { ClinicalDataType clinicalDataType = attributeDatatypeMap.get(attribute.getAttributeId()); List filteredIds = clinicalDataType == ClinicalDataType.PATIENT @@ -326,38 +366,53 @@ public List calculateDynamicDataBins( List dataBins = dataBinner .calculateDataBins(attribute, clinicalDataType, filteredClinicalDataByAttributeId.getOrDefault(attribute.getAttributeId(), - Collections.emptyList()), + emptyList()), filteredIds) .stream() .map(dataBin -> studyViewFilterUtil.dataBinToClinicalDataBin(attribute, dataBin)) - .collect(Collectors.toList()); + .collect(toList()); clinicalDataBins.addAll(dataBins); } } return clinicalDataBins; } - - public Map constructAttributeDataMap( + private Map toAttributeDatatypeMap(BinningIds binningIds) { + return toAttributeDatatypeMap( + binningIds.getSampleAttributeIds(), + binningIds.getPatientAttributeIds(), + binningIds.getConflictingPatientAttributeIds() + ); + } + public Map toAttributeDatatypeMap( List sampleAttributeIds, List patientAttributeIds, List conflictingPatientAttributeIds ) { Map attributeDatatypeMap = new HashMap<>(); - sampleAttributeIds.forEach(attribute->{ + sampleAttributeIds.forEach(attribute -> { attributeDatatypeMap.put(attribute, ClinicalDataType.SAMPLE); }); - patientAttributeIds.forEach(attribute->{ + patientAttributeIds.forEach(attribute -> { attributeDatatypeMap.put(attribute, ClinicalDataType.PATIENT); }); - conflictingPatientAttributeIds.forEach(attribute->{ + conflictingPatientAttributeIds.forEach(attribute -> { attributeDatatypeMap.put(attribute, ClinicalDataType.SAMPLE); }); return attributeDatatypeMap; } + private Map createCustomAttributeDatatypeMap( + Map customDataSessions + ) { + return customDataSessions.entrySet().stream().collect(toMap( + Map.Entry::getKey, + ClinicalDataBinUtil::getDataType + )); + } + public List filterByStudyAndSample( StudyViewFilter studyViewFilter ) { @@ -372,4 +427,22 @@ public List filterByStudyAndSample( return studyViewFilterApplier.apply(filter); } + + private static ClinicalDataType getDataType(Map.Entry entry) { + return entry.getValue().getData().getPatientAttribute() ? ClinicalDataType.PATIENT : ClinicalDataType.SAMPLE; + } + + private List fetchClinicalAttributes(List attributeIds, List unfilteredSamples) { + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds( + unfilteredSamples, + studyIds, + sampleIds + ); + + return clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds(studyIds, attributeIds); + } + } diff --git a/web/src/main/java/org/cbioportal/web/util/ClinicalDataEqualityFilterApplier.java b/web/src/main/java/org/cbioportal/web/util/ClinicalDataEqualityFilterApplier.java index 2e82b156fe9..91ce735b31f 100644 --- a/web/src/main/java/org/cbioportal/web/util/ClinicalDataEqualityFilterApplier.java +++ b/web/src/main/java/org/cbioportal/web/util/ClinicalDataEqualityFilterApplier.java @@ -26,7 +26,8 @@ public Integer apply(List attributes, MultiKeyMap clinicalDataMap, String entityId, String studyId, - Boolean negateFilters) { + Boolean negateFilters + ) { return studyViewFilterUtil.getFilteredCountByDataEquality(attributes, clinicalDataMap, entityId, studyId, negateFilters); } } diff --git a/web/src/main/java/org/cbioportal/web/util/ClinicalDataFilterApplier.java b/web/src/main/java/org/cbioportal/web/util/ClinicalDataFilterApplier.java index 68c3b802a79..8e062c2ff33 100644 --- a/web/src/main/java/org/cbioportal/web/util/ClinicalDataFilterApplier.java +++ b/web/src/main/java/org/cbioportal/web/util/ClinicalDataFilterApplier.java @@ -13,22 +13,27 @@ import org.cbioportal.web.parameter.Projection; import org.cbioportal.web.parameter.SampleIdentifier; -public abstract class ClinicalDataFilterApplier { +public abstract class ClinicalDataFilterApplier implements DataFilterApplier { private PatientService patientService; private ClinicalDataService clinicalDataService; protected StudyViewFilterUtil studyViewFilterUtil; - public ClinicalDataFilterApplier(PatientService patientService, - ClinicalDataService clinicalDataService, - StudyViewFilterUtil studyViewFilterUtil) { + public ClinicalDataFilterApplier( + PatientService patientService, + ClinicalDataService clinicalDataService, + StudyViewFilterUtil studyViewFilterUtil + ) { this.patientService = patientService; this.clinicalDataService = clinicalDataService; this.studyViewFilterUtil = studyViewFilterUtil; } - public List apply(List sampleIdentifiers, - List clinicalDataFilters, - Boolean negateFilters) { + @Override + public List apply( + List sampleIdentifiers, + List clinicalDataFilters, + Boolean negateFilters + ) { if (!clinicalDataFilters.isEmpty() && !sampleIdentifiers.isEmpty()) { List studyIds = new ArrayList<>(); List sampleIds = new ArrayList<>(); diff --git a/web/src/main/java/org/cbioportal/web/util/CustomDataFilterApplier.java b/web/src/main/java/org/cbioportal/web/util/CustomDataFilterApplier.java index 5f30bde20b6..447a0e5d691 100644 --- a/web/src/main/java/org/cbioportal/web/util/CustomDataFilterApplier.java +++ b/web/src/main/java/org/cbioportal/web/util/CustomDataFilterApplier.java @@ -1,88 +1,132 @@ package org.cbioportal.web.util; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; -import java.util.stream.Collectors; - import org.apache.commons.collections4.map.MultiKeyMap; -import org.cbioportal.service.ClinicalDataService; -import org.cbioportal.service.PatientService; -import org.cbioportal.session_service.domain.SessionType; +import org.cbioportal.service.CustomDataService; +import org.cbioportal.service.util.CustomDataSession; import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.cbioportal.web.parameter.CustomDataSession; import org.cbioportal.web.parameter.SampleIdentifier; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + @Component -public class CustomDataFilterApplier extends ClinicalDataEqualityFilterApplier { +public class CustomDataFilterApplier implements DataFilterApplier { - @Autowired - public CustomDataFilterApplier(PatientService patientService, ClinicalDataService clinicalDataService, - StudyViewFilterUtil studyViewFilterUtil) { - super(patientService, clinicalDataService, studyViewFilterUtil); - } + private CustomDataService customDataService; + private ClinicalDataEqualityFilterApplier equalityFilterApplier; + private ClinicalDataIntervalFilterApplier intervalFilterApplier; + @Autowired - private SessionServiceRequestHandler sessionServiceRequestHandler; + public CustomDataFilterApplier( + CustomDataService customDataService, + ClinicalDataEqualityFilterApplier equalityFilterApplier, + ClinicalDataIntervalFilterApplier intervalFilterApplier + ) { + this.customDataService = customDataService; + this.equalityFilterApplier = equalityFilterApplier; + this.intervalFilterApplier = intervalFilterApplier; + } @Override - public List apply(List sampleIdentifiers, - List customDataFilters, Boolean negateFilters) { - if (!customDataFilters.isEmpty() && !sampleIdentifiers.isEmpty()) { - - List> postFutures = customDataFilters.stream() - .map(clinicalDataFilter -> { - return CompletableFuture.supplyAsync(() -> { - try { - return (CustomDataSession) sessionServiceRequestHandler - .getSession(SessionType.custom_data, clinicalDataFilter.getAttributeId()); - } catch (Exception e) { - return null; - } - }); - }).collect(Collectors.toList()); - - CompletableFuture.allOf(postFutures.toArray(new CompletableFuture[postFutures.size()])).join(); + public List apply( + List sampleIdentifiers, + List dataFilters, + Boolean negateFilters + ) { + if (dataFilters.isEmpty() || sampleIdentifiers.isEmpty()) { + return sampleIdentifiers; + } - Map customDataSessionById = postFutures - .stream() - .map(CompletableFuture::join) - .filter(Objects::nonNull) - .collect(Collectors.toMap(CustomDataSession::getId, Function.identity())); + final List attributeIds = dataFilters.stream() + .map(ClinicalDataFilter::getAttributeId) + .collect(Collectors.toList()); - MultiKeyMap clinicalDataMap = new MultiKeyMap(); + final Map customDataSessions = customDataService.getCustomDataSessions(attributeIds); - customDataSessionById.values() + Map customDataSessionById = customDataSessions + .values() .stream() - .forEach(customDataSession -> { - customDataSession.getData().getData().forEach(datum -> { - String value = datum.getValue().toUpperCase(); - if (value.equals("NAN") || value.equals("N/A")) { - value = "NA"; - } - clinicalDataMap.put(datum.getStudyId(), datum.getSampleId(), customDataSession.getId(), value); - }); - }); - - List newSampleIdentifiers = new ArrayList<>(); - - sampleIdentifiers.forEach(sampleIdentifier -> { - int count = apply(customDataFilters, clinicalDataMap, - sampleIdentifier.getSampleId(), sampleIdentifier.getStudyId(), negateFilters); - - if (count == customDataFilters.size()) { - newSampleIdentifiers.add(sampleIdentifier); + .collect(Collectors.toMap( + CustomDataSession::getId, + Function.identity() + )); + + /* + Custom data entry with: + - key1: studyId; + - key2: sampleId; + - key3: sessionId. + */ + MultiKeyMap customDataByStudySampleSession = new MultiKeyMap<>(); + + customDataSessionById.values().forEach(customDataSession -> customDataSession + .getData() + .getData() + .forEach(datum -> { + String value = datum.getValue().toUpperCase(); + if (value.equals("NAN") || value.equals("N/A")) { + value = "NA"; } - }); - - return newSampleIdentifiers; - } - return sampleIdentifiers; + customDataByStudySampleSession.put(datum.getStudyId(), datum.getSampleId(), customDataSession.getId(), value); + }) + ); + + return filterCustomData( + dataFilters, + negateFilters, + sampleIdentifiers, + customDataSessionById, + customDataByStudySampleSession + ); } - + + private List filterCustomData( + List customDataFilters, + Boolean negateFilters, + List sampleIdentifiers, + Map customDataSessionById, + MultiKeyMap clinicalDataMap + ) { + List equalityFilters = new ArrayList<>(); + List intervalFilters = new ArrayList<>(); + + customDataFilters.forEach(filter -> { + String attributeId = filter.getAttributeId(); + if (!customDataSessionById.containsKey(attributeId)) { + return; + } + if (customDataSessionById + .get(attributeId) + .getData() + .getDatatype() + .equals(CustomDatatype.STRING.name()) + ) { + equalityFilters.add(filter); + } else { + intervalFilters.add(filter); + } + }); + + List filtered = new ArrayList<>(); + sampleIdentifiers.forEach(sampleIdentifier -> { + int equalityFilterCount = equalityFilterApplier.apply(equalityFilters, clinicalDataMap, + sampleIdentifier.getSampleId(), sampleIdentifier.getStudyId(), negateFilters); + int intervalFilterCount = intervalFilterApplier.apply(intervalFilters, clinicalDataMap, + sampleIdentifier.getSampleId(), sampleIdentifier.getStudyId(), negateFilters); + if (equalityFilterCount == equalityFilters.size() + && intervalFilterCount == intervalFilters.size() + ) { + filtered.add(sampleIdentifier); + } + }); + + return filtered; + } + } diff --git a/web/src/main/java/org/cbioportal/web/util/CustomDatatype.java b/web/src/main/java/org/cbioportal/web/util/CustomDatatype.java new file mode 100644 index 00000000000..9aaac0ebd15 --- /dev/null +++ b/web/src/main/java/org/cbioportal/web/util/CustomDatatype.java @@ -0,0 +1,13 @@ +package org.cbioportal.web.util; + +public enum CustomDatatype { + /** + * Categorical data + */ + STRING, + + /** + * Numerical data + */ + NUMBER +} \ No newline at end of file diff --git a/web/src/main/java/org/cbioportal/web/util/DataBinner.java b/web/src/main/java/org/cbioportal/web/util/DataBinner.java index 65c386d607e..e478bd61aa4 100644 --- a/web/src/main/java/org/cbioportal/web/util/DataBinner.java +++ b/web/src/main/java/org/cbioportal/web/util/DataBinner.java @@ -2,6 +2,8 @@ import com.google.common.collect.Range; import org.apache.commons.lang3.math.NumberUtils; +import org.cbioportal.model.Binnable; +import org.cbioportal.model.ClinicalData; import org.cbioportal.model.ClinicalData; import org.cbioportal.model.DataBin; import org.cbioportal.web.parameter.BinsGeneratorConfig; @@ -33,22 +35,22 @@ public class DataBinner { private LogScaleDataBinner logScaleDataBinner; public List calculateClinicalDataBins(T dataBinFilter, - ClinicalDataType clinicalDataType, - List filteredClinicalData, - List unfilteredClinicalData, - List filteredIds, + ClinicalDataType clinicalDataType, + List filteredClinicalData, + List unfilteredClinicalData, + List filteredIds, List unfilteredIds) { // calculate data bins for unfiltered clinical data List dataBins = calculateDataBins( dataBinFilter, clinicalDataType, unfilteredClinicalData, unfilteredIds); - + // recount return recalcBinCount(dataBins, clinicalDataType, filteredClinicalData, filteredIds); } public List recalcBinCount(List dataBins, ClinicalDataType clinicalDataType, - List clinicalData, + List clinicalData, List ids) { List numericalValues = clinicalData == null ? Collections.emptyList() : filterNumericalValues(clinicalData); @@ -65,19 +67,19 @@ public List recalcBinCount(List dataBins, Range range = dataBinHelper.calcRange(dataBin); if (range != null) { - for (BigDecimal value: numericalValues) { + for (BigDecimal value : numericalValues) { if (range.contains(value)) { dataBin.setCount(dataBin.getCount() + 1); } } - for (Range r: ranges) { + for (Range r : ranges) { if (range.encloses(r)) { dataBin.setCount(dataBin.getCount() + 1); } } } else { // if no range then it means non numerical data bin - for (String value: nonNumericalValues) { + for (String value : nonNumericalValues) { if (value.equalsIgnoreCase(dataBin.getSpecialValue())) { dataBin.setCount(dataBin.getCount() + 1); } @@ -94,7 +96,7 @@ public List recalcBinCount(List dataBins, public List calculateDataBins( T dataBinFilter, ClinicalDataType clinicalDataType, - List clinicalData, + List clinicalData, List ids ) { return calculateDataBins( @@ -105,11 +107,11 @@ public List calculateDataBins( DEFAULT_DISTINCT_VALUE_THRESHOLD ); } - + public List calculateDataBins( T dataBinFilter, ClinicalDataType clinicalDataType, - List clinicalData, + List clinicalData, List ids, Integer distinctValueThreshold ) { @@ -162,8 +164,8 @@ public List calculateDataBins( dataBins = dataBinHelper.convertToDistinctBins( dataBins, filterNumericalValues(clinicalData), filterSpecialRanges(clinicalData) ); - - if(!numericalOnly) { + + if (!numericalOnly) { // add non numerical and NA data bins dataBins.addAll(calcNonNumericalClinicalDataBins(clinicalData)); @@ -177,29 +179,29 @@ dataBins, filterNumericalValues(clinicalData), filterSpecialRanges(clinicalData) return dataBins; } - public List> filterSpecialRanges(List clinicalData) { + public List> filterSpecialRanges(List clinicalData) { return clinicalData.stream() - .map(ClinicalData::getAttrValue) + .map(Binnable::getAttrValue) .filter(s -> (s.contains(">") || s.contains("<")) && // ignore any invalid values such as >10PY, <20%, etc. NumberUtils.isCreatable(dataBinHelper.stripOperator(s))) .map(v -> dataBinHelper.calcRange( // only use "<" or ">" to make sure that we only generate open ranges - dataBinHelper.extractOperator(v).substring(0,1), + dataBinHelper.extractOperator(v).substring(0, 1), new BigDecimal(dataBinHelper.stripOperator(v)))) .collect(Collectors.toList()); } - public Collection calcNonNumericalClinicalDataBins(List clinicalData) { + public Collection calcNonNumericalClinicalDataBins(List clinicalData) { return calcNonNumericalDataBins(filterNonNumericalValues(clinicalData)); } - public List filterNonNumericalValues(List clinicalData) { + public List filterNonNumericalValues(List clinicalData) { // filter out numerical values and 'NA's return clinicalData.stream() - .map(ClinicalData::getAttrValue) - .filter(s -> !NumberUtils.isCreatable(dataBinHelper.stripOperator(s)) && !dataBinHelper.isNA(s)) - .collect(Collectors.toList()); + .map(Binnable::getAttrValue) + .filter(s -> !NumberUtils.isCreatable(dataBinHelper.stripOperator(s)) && !dataBinHelper.isNA(s)) + .collect(Collectors.toList()); } public Collection calcNonNumericalDataBins(List nonNumericalValues) { @@ -221,7 +223,7 @@ public Collection calcNonNumericalDataBins(List nonNumericalVal public Collection calcNumericalClinicalDataBins( DataBinFilter dataBinFilter, - List clinicalData, + List clinicalData, List customBins, DataBinFilter.BinMethod binMethod, BinsGeneratorConfig binsGeneratorConfig, @@ -243,7 +245,7 @@ public Collection calcNumericalClinicalDataBi ); } - public List filterNumericalValues(List clinicalData) { + public List filterNumericalValues(List clinicalData) { // filter out invalid values return clinicalData.stream() .filter(c -> NumberUtils.isCreatable(c.getAttrValue())) @@ -262,12 +264,12 @@ public Collection calcNumericalDataBins( Boolean disableLogScale, Integer distinctValueThreshold ) { - + Predicate isLowerOutlier = d -> ( lowerOutlierBin != null && lowerOutlierBin.getEnd() != null && (lowerOutlierBin.getSpecialValue() != null && lowerOutlierBin.getSpecialValue().contains("=") ? - d.compareTo(lowerOutlierBin.getEnd()) != 1 : d.compareTo(lowerOutlierBin.getEnd()) == -1) + d.compareTo(lowerOutlierBin.getEnd()) != 1 : d.compareTo(lowerOutlierBin.getEnd()) == -1) ); Predicate isUpperOutlier = d -> ( @@ -311,7 +313,7 @@ public Collection calcNumericalDataBins( } else if (DataBinFilter.BinMethod.QUARTILE == binMethod) { List boundaries = this.dataBinHelper.calcQuartileBoundaries(sortedNumericalValues); dataBins = linearDataBinner.calculateDataBins(boundaries, numericalValues); - } else if (boxRange.upperEndpoint().subtract(boxRange.lowerEndpoint()).compareTo(new BigDecimal(1000)) == 1 && + } else if (boxRange.upperEndpoint().subtract(boxRange.lowerEndpoint()).compareTo(new BigDecimal(1000)) == 1 && (disableLogScale == null || !disableLogScale)) { dataBins = logScaleDataBinner.calculateDataBins( boxRange, @@ -340,18 +342,18 @@ public Collection calcNumericalDataBins( } BigDecimal lowerOutlier = lowerOutlierBin.getEnd() == null ? boxRange.lowerEndpoint() - : boxRange.lowerEndpoint().max(lowerOutlierBin.getEnd()); + : boxRange.lowerEndpoint().max(lowerOutlierBin.getEnd()); BigDecimal upperOutlier = upperOutlierBin.getStart() == null ? boxRange.upperEndpoint() - : boxRange.upperEndpoint().min(upperOutlierBin.getStart()); + : boxRange.upperEndpoint().min(upperOutlierBin.getStart()); Optional attributeId = dataBinFilter instanceof ClinicalDataBinFilter - ? Optional.of(((ClinicalDataBinFilter) dataBinFilter).getAttributeId()) - : Optional.empty(); + ? Optional.of(((ClinicalDataBinFilter) dataBinFilter).getAttributeId()) + : Optional.empty(); dataBins = linearDataBinner.calculateDataBins(areAllIntegers, boxRange, withoutOutliers, lowerOutlier, - upperOutlier, attributeId); + upperOutlier, attributeId); } - + if (DataBinFilter.BinMethod.MEDIAN == binMethod // In edge cases all quartile values can be identical (all // values are in the outlier bins). @@ -359,7 +361,7 @@ public Collection calcNumericalDataBins( BigDecimal median = this.dataBinHelper.calcMedian(sortedNumericalValues); lowerOutlierBin.setEnd(median); upperOutlierBin.setStart(median); - // Covers the situation where there is a single custom boundary (i.e. there are only outlier bins). + // Covers the situation where there is a single custom boundary (i.e. there are only outlier bins). } else if (DataBinFilter.BinMethod.CUSTOM == binMethod && customBins != null && customBins.size() == 1) { lowerOutlierBin.setEnd(customBins.get(0)); @@ -421,22 +423,22 @@ public Collection calcNumericalDataBins( return dataBins; } - public List doubleValuesForSpecialOutliers(List clinicalData, String operator) { + public List doubleValuesForSpecialOutliers(List clinicalData, String operator) { return ( // find the ones starting with the operator clinicalData.stream().filter(c -> c.getAttrValue().trim().startsWith(operator)) - // strip the operator - .map(c -> c.getAttrValue().trim().substring(operator.length())) - // filter out invalid values - .filter(NumberUtils::isCreatable) - // parse the numerical value as a BigDecimal instance - .map(integer -> new BigDecimal(integer)) - // collect as list - .collect(Collectors.toList()) + // strip the operator + .map(c -> c.getAttrValue().trim().substring(operator.length())) + // filter out invalid values + .filter(NumberUtils::isCreatable) + // parse the numerical value as a BigDecimal instance + .map(integer -> new BigDecimal(integer)) + // collect as list + .collect(Collectors.toList()) ); } - public List filterSmallerThanUpperBound(List clinicalData, BigDecimal value) { + public List filterSmallerThanUpperBound(List clinicalData, BigDecimal value) { return ( clinicalData.stream() .filter(c -> NumberUtils.isCreatable(c.getAttrValue()) && new BigDecimal(c.getAttrValue()).compareTo(value) != 1) @@ -444,7 +446,7 @@ public List filterSmallerThanUpperBound(List clinica ); } - public List filterBiggerThanLowerBound(List clinicalData, BigDecimal value) { + public List filterBiggerThanLowerBound(List clinicalData, BigDecimal value) { return ( clinicalData.stream() .filter(c -> NumberUtils.isCreatable(c.getAttrValue()) && new BigDecimal(c.getAttrValue()).compareTo(value) != -1) @@ -453,7 +455,7 @@ public List filterBiggerThanLowerBound(List clinical ); } - public DataBin calcUpperOutlierBin(List clinicalData) { + public DataBin calcUpperOutlierBin(List clinicalData) { DataBin dataBin = dataBinHelper.calcUpperOutlierBin( doubleValuesForSpecialOutliers(clinicalData, ">="), doubleValuesForSpecialOutliers(clinicalData, ">")); @@ -464,7 +466,7 @@ public DataBin calcUpperOutlierBin(List clinicalData) { return dataBin; } - public DataBin calcLowerOutlierBin(List clinicalData) { + public DataBin calcLowerOutlierBin(List clinicalData) { DataBin dataBin = dataBinHelper.calcLowerOutlierBin( doubleValuesForSpecialOutliers(clinicalData, "<="), doubleValuesForSpecialOutliers(clinicalData, "<")); @@ -479,9 +481,9 @@ public DataBin calcLowerOutlierBin(List clinicalData) { * We cannot do an exact calculation for values below/above the special outlier values. * We need to adjust custom bins for those cases. * - * example: assume we have special values <18 and >90 in our dataset - * custom bins => [10, 15, 40, 70, 95, 100] - * adjusted custom bins => [18, 40, 70, 90] + * example: assume we have special values <18 and >90 in our dataset + * custom bins => [10, 15, 40, 70, 95, 100] + * adjusted custom bins => [18, 40, 70, 90] */ public List adjustCustomBins( List customBins, @@ -507,20 +509,20 @@ public List adjustCustomBins( if (customBins.stream().anyMatch(bin -> upperBound != null && bin.compareTo(upperBound) == 1)) { binsWithinBounds.add(upperBound); } - + return binsWithinBounds; } - + /** * NA count is: Number of clinical data marked actually as "NA" + Number of patients/samples without clinical data. * Assuming that clinical data is for a single attribute. * - * @param clinicalData clinical data list for a single attribute - * @param ids sample/patient ids + * @param clinicalData clinical data list for a single attribute + * @param ids sample/patient ids * * @return 'NA' clinical data count as a DataBin instance */ - public DataBin calcNaDataBin(List clinicalData, + public DataBin calcNaDataBin(List clinicalData, ClinicalDataType clinicalDataType, List ids) { DataBin bin = new DataBin(); @@ -534,13 +536,13 @@ public DataBin calcNaDataBin(List clinicalData, return bin; } - public Long countNAs(List clinicalData, ClinicalDataType clinicalDataType, List ids) { + public Long countNAs(List clinicalData, ClinicalDataType clinicalDataType, List ids) { // Calculate number of clinical data marked actually as "NA", "NAN", or "N/A" Long count = clinicalData == null ? 0 : clinicalData.stream() - .filter(c -> dataBinHelper.isNA(c.getAttrValue())) - .count(); + .filter(c -> dataBinHelper.isNA(c.getAttrValue())) + .count(); // Calculate number of patients/samples without clinical data @@ -566,9 +568,9 @@ public Long countNAs(List clinicalData, ClinicalDataType clinicalD return count; } - private String computeUniqueCaseId(ClinicalData clinicalData, ClinicalDataType clinicalDataType) { + private String computeUniqueCaseId(Binnable clinicalData, ClinicalDataType clinicalDataType) { return clinicalData.getStudyId() + (clinicalDataType == ClinicalDataType.PATIENT - ? clinicalData.getPatientId() - : clinicalData.getSampleId()); + ? clinicalData.getPatientId() + : clinicalData.getSampleId()); } } diff --git a/web/src/main/java/org/cbioportal/web/util/DataFilterApplier.java b/web/src/main/java/org/cbioportal/web/util/DataFilterApplier.java new file mode 100644 index 00000000000..172931160a3 --- /dev/null +++ b/web/src/main/java/org/cbioportal/web/util/DataFilterApplier.java @@ -0,0 +1,15 @@ +package org.cbioportal.web.util; + +import org.cbioportal.web.parameter.DataFilter; +import org.cbioportal.web.parameter.SampleIdentifier; + +import java.util.List; + +public interface DataFilterApplier { + + List apply( + List sampleIdentifiers, + List dataFilters, + Boolean negateFilters + ); +} diff --git a/web/src/main/java/org/cbioportal/web/util/IdPopulator.java b/web/src/main/java/org/cbioportal/web/util/IdPopulator.java new file mode 100644 index 00000000000..bfda0b01e95 --- /dev/null +++ b/web/src/main/java/org/cbioportal/web/util/IdPopulator.java @@ -0,0 +1,68 @@ +package org.cbioportal.web.util; + +import org.cbioportal.model.ClinicalAttribute; +import org.cbioportal.service.AttributeByStudyService; +import org.cbioportal.service.PatientService; +import org.cbioportal.service.util.ClinicalAttributeUtil; +import org.cbioportal.web.parameter.SampleIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Component +public class IdPopulator { + + @Autowired + private ClinicalAttributeUtil clinicalAttributeUtil; + @Autowired + private StudyViewFilterApplier studyViewFilterApplier; + @Autowired + private StudyViewFilterUtil studyViewFilterUtil; + @Autowired + private PatientService patientService; + + public IdPopulator() {} + + public BinningIds populateIdLists( + List samples, + List clinicalAttributes + ) { + BinningIds binningIds = new BinningIds(); + List studyIds = binningIds.getStudyIds(); + List sampleIds = binningIds.getSampleIds(); + List patientIds = binningIds.getPatientIds(); + List studyIdsOfPatients = binningIds.getStudyIdsOfPatients(); + List uniqueSampleKeys = binningIds.getUniqueSampleKeys(); + List uniquePatientKeys = binningIds.getUniquePatientKeys(); + List sampleAttributeIds = binningIds.getSampleAttributeIds(); + List patientAttributeIds = binningIds.getPatientAttributeIds(); + List conflictingPatientAttributeIds = binningIds.getConflictingPatientAttributeIds(); + + studyViewFilterUtil.extractStudyAndSampleIds( + samples, + studyIds, + sampleIds + ); + + patientService.getPatientsOfSamples(studyIds, sampleIds).forEach(patient -> { + patientIds.add(patient.getStableId()); + studyIdsOfPatients.add(patient.getCancerStudyIdentifier()); + }); + + uniqueSampleKeys.addAll(studyViewFilterApplier.getUniqkeyKeys(studyIds, sampleIds)); + uniquePatientKeys.addAll(studyViewFilterApplier.getUniqkeyKeys(studyIdsOfPatients, patientIds)); + + if (clinicalAttributes != null && !clinicalAttributes.isEmpty()) { + clinicalAttributeUtil.extractCategorizedClinicalAttributes( + clinicalAttributes, + sampleAttributeIds, + patientAttributeIds, + conflictingPatientAttributeIds + ); + } + return binningIds; + } + +} diff --git a/web/src/main/java/org/cbioportal/web/util/InvolvedCancerStudyExtractorInterceptor.java b/web/src/main/java/org/cbioportal/web/util/InvolvedCancerStudyExtractorInterceptor.java index 99aaf69b754..91720ee1f81 100644 --- a/web/src/main/java/org/cbioportal/web/util/InvolvedCancerStudyExtractorInterceptor.java +++ b/web/src/main/java/org/cbioportal/web/util/InvolvedCancerStudyExtractorInterceptor.java @@ -73,7 +73,9 @@ public class InvolvedCancerStudyExtractorInterceptor extends HandlerInterceptorA public static final String MUTATION_MULTIPLE_STUDY_FETCH_PATH = "/mutations/fetch"; public static final String COPY_NUMBER_SEG_FETCH_PATH = "/copy-number-segments/fetch"; public static final String STUDY_VIEW_CLINICAL_DATA_BIN_COUNTS_PATH = "/clinical-data-bin-counts/fetch"; + public static final String STUDY_VIEW_CUSTOM_DATA_BIN_COUNTS_PATH = "/custom-data-bin-counts/fetch"; public static final String STUDY_VIEW_GENOMICL_DATA_BIN_COUNTS_PATH = "/genomic-data-bin-counts/fetch"; + public static final String STUDY_VIEW_GENOMICL_DATA_COUNTS_PATH = "/genomic-data-counts/fetch"; public static final String STUDY_VIEW_GENERIC_ASSAY_DATA_BIN_COUNTS_PATH = "/generic-assay-data-bin-counts/fetch"; public static final String STUDY_VIEW_GENERIC_ASSAY_DATA_COUNTS_PATH = "/generic-assay-data-counts/fetch"; public static final String STUDY_VIEW_CLINICAL_DATA_COUNTS_PATH = "/clinical-data-counts/fetch"; @@ -84,6 +86,7 @@ public class InvolvedCancerStudyExtractorInterceptor extends HandlerInterceptorA public static final String STUDY_VIEW_FILTERED_SAMPLES = "/filtered-samples/fetch"; public static final String STUDY_VIEW_MUTATED_GENES = "/mutated-genes/fetch"; public static final String STUDY_VIEW_STRUCTURAL_VARIANT_GENES = "/structuralvariant-genes/fetch"; + public static final String STUDY_VIEW_STRUCTURAL_VARIANT_COUNTS = "/structuralvariant-counts/fetch"; public static final String STUDY_VIEW_SAMPLE_COUNTS = "/sample-counts/fetch"; public static final String STUDY_VIEW_SAMPLE_LIST_COUNTS_PATH = "/sample-lists-counts/fetch"; public static final String STUDY_VIEW_CLINICAL_TABLE_DATA_FETCH_PATH = "/clinical-data-table/fetch"; @@ -99,6 +102,8 @@ public class InvolvedCancerStudyExtractorInterceptor extends HandlerInterceptorA public static final String TREATMENTS_PATIENT_PATH = "/treatments/patient"; public static final String TREATMENTS_SAMPLE_PATH = "/treatments/sample"; public static final String GENERIC_ASSAY_ENRICHMENT_FETCH_PATH = "/generic-assay-enrichments/fetch"; + public static final String GENERIC_ASSAY_CATEGORICAL_ENRICHMENT_FETCH_PATH = "/generic-assay-categorical-enrichments/fetch"; + public static final String GENERIC_ASSAY_BINARY_ENRICHMENT_FETCH_PATH = "/generic-assay-binary-enrichments/fetch"; public static final String CLINICAL_EVENT_TYPE_COUNT_FETCH_PATH = "/clinical-event-type-counts/fetch"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { @@ -124,10 +129,12 @@ public class InvolvedCancerStudyExtractorInterceptor extends HandlerInterceptorA return extractAttributesFromMutationMultipleStudyFilter(request); } else if (requestPathInfo.equals(COPY_NUMBER_SEG_FETCH_PATH)) { return extractAttributesFromSampleIdentifiers(request); - } else if (requestPathInfo.equals(STUDY_VIEW_CLINICAL_DATA_BIN_COUNTS_PATH)) { + } else if (Arrays.asList(STUDY_VIEW_CLINICAL_DATA_BIN_COUNTS_PATH, STUDY_VIEW_CUSTOM_DATA_BIN_COUNTS_PATH).contains(requestPathInfo)) { return extractAttributesFromClinicalDataBinCountFilter(request); } else if (requestPathInfo.equals(STUDY_VIEW_GENOMICL_DATA_BIN_COUNTS_PATH)) { return extractAttributesFromGenomicDataBinCountFilter(request); + } else if (requestPathInfo.equals(STUDY_VIEW_GENOMICL_DATA_COUNTS_PATH)) { + return extractAttributesFromGenomicDataCountFilter(request); } else if (requestPathInfo.equals(STUDY_VIEW_GENERIC_ASSAY_DATA_BIN_COUNTS_PATH)) { return extractAttributesFromGenericAssayDataBinCountFilter(request); } else if (requestPathInfo.equals(STUDY_VIEW_GENERIC_ASSAY_DATA_COUNTS_PATH)) { @@ -135,9 +142,9 @@ public class InvolvedCancerStudyExtractorInterceptor extends HandlerInterceptorA } else if (Arrays.asList(STUDY_VIEW_CLINICAL_DATA_COUNTS_PATH, STUDY_VIEW_CUSTOM_DATA_COUNTS_PATH) .contains(requestPathInfo)) { return extractAttributesFromClinicalDataCountFilter(request); - } else if (Arrays.asList(STUDY_VIEW_CLINICAL_DATA_DENSITY_PATH, STUDY_VIEW_CLINICAL_DATA_VIOLIN_PATH, STUDY_VIEW_CNA_GENES, + } else if (Arrays.asList(STUDY_VIEW_CLINICAL_DATA_DENSITY_PATH, STUDY_VIEW_CLINICAL_DATA_VIOLIN_PATH, STUDY_VIEW_CNA_GENES, STUDY_VIEW_FILTERED_SAMPLES, STUDY_VIEW_MUTATED_GENES, STUDY_VIEW_STRUCTURAL_VARIANT_GENES, - STUDY_VIEW_SAMPLE_COUNTS, STUDY_VIEW_SAMPLE_LIST_COUNTS_PATH, STUDY_VIEW_CLINICAL_TABLE_DATA_FETCH_PATH, + STUDY_VIEW_STRUCTURAL_VARIANT_COUNTS, STUDY_VIEW_SAMPLE_COUNTS, STUDY_VIEW_SAMPLE_LIST_COUNTS_PATH, STUDY_VIEW_CLINICAL_TABLE_DATA_FETCH_PATH, TREATMENTS_PATIENT_PATH, TREATMENTS_SAMPLE_PATH, STUDY_VIEW_PROFILE_SAMPLE_COUNTS_PATH, CLINICAL_EVENT_TYPE_COUNT_FETCH_PATH ).contains(requestPathInfo)) { return extractAttributesFromStudyViewFilter(request); @@ -146,7 +153,9 @@ public class InvolvedCancerStudyExtractorInterceptor extends HandlerInterceptorA } else if (requestPathInfo.equals(MUTATION_ENRICHMENT_FETCH_PATH) || requestPathInfo.equals(COPY_NUMBER_ENRICHMENT_FETCH_PATH) || requestPathInfo.equals(EXPRESSION_ENRICHMENT_FETCH_PATH) || - requestPathInfo.equals(GENERIC_ASSAY_ENRICHMENT_FETCH_PATH)) { + requestPathInfo.equals(GENERIC_ASSAY_ENRICHMENT_FETCH_PATH) || + requestPathInfo.equals(GENERIC_ASSAY_CATEGORICAL_ENRICHMENT_FETCH_PATH) || + requestPathInfo.equals(GENERIC_ASSAY_BINARY_ENRICHMENT_FETCH_PATH)) { return extractAttributesFromMolecularProfileCasesGroups(request); } else if (requestPathInfo.equals(ALTERATION_ENRICHMENT_FETCH_PATH)) { return extractAttributesFromMolecularProfileCasesGroupsAndAlterationTypes(request); @@ -475,6 +484,26 @@ private boolean extractAttributesFromGenomicDataBinCountFilter(HttpServletReques return true; } + private boolean extractAttributesFromGenomicDataCountFilter(HttpServletRequest request) { + try { + GenomicDataCountFilter genomicDataCountFilter = objectMapper.readValue(request.getInputStream(), + GenomicDataCountFilter.class); + LOG.debug("extracted genomicDataCountFilter: " + genomicDataCountFilter.toString()); + LOG.debug("setting interceptedGenomicDataCountFilter to " + genomicDataCountFilter); + request.setAttribute("interceptedGenomicDataCountFilter", genomicDataCountFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = extractCancerStudyIdsFromGenomicDataCountFilter( + genomicDataCountFilter); + LOG.debug("setting involvedCancerStudies to " + cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error("exception thrown during extraction of genomicDataCountFilter: " + e); + return false; + } + return true; + } + private boolean extractAttributesFromGenericAssayDataBinCountFilter(HttpServletRequest request) { try { GenericAssayDataBinCountFilter genericAssayDataBinCountFilter = objectMapper @@ -564,6 +593,11 @@ private boolean extractAttributesFromStudyViewFilter(HttpServletRequest request) // when the AlterationFilter is not part of the request. studyViewFilter.setAlterationFilter(new AlterationFilter()); } + if (studyViewFilter.getStructuralVariantFilters() == null) { + // For backwards compatibility an inactive filter is set + // when the StructuralVariantFilters are not part of the request. + studyViewFilter.setStructuralVariantFilters(new ArrayList<>()); + } LOG.debug("extracted studyViewFilter: " + studyViewFilter.toString()); LOG.debug("setting interceptedStudyViewFilter to " + studyViewFilter); request.setAttribute("interceptedStudyViewFilter", studyViewFilter); @@ -715,6 +749,14 @@ private Set extractCancerStudyIdsFromGenomicDataBinCountFilter( return new HashSet(); } + private Set extractCancerStudyIdsFromGenomicDataCountFilter( + GenomicDataCountFilter genomicDataCountFilter) { + if (genomicDataCountFilter.getStudyViewFilter() != null) { + return extractCancerStudyIdsFromStudyViewFilter(genomicDataCountFilter.getStudyViewFilter()); + } + return new HashSet(); + } + private Set extractCancerStudyIdsFromGenericAssayDataBinCountFilter( GenericAssayDataBinCountFilter genericAssayDataBinCountFilter) { if (genericAssayDataBinCountFilter.getStudyViewFilter() != null) { diff --git a/web/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java b/web/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java index 3cd9c5a41d0..0b97b6df954 100644 --- a/web/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java +++ b/web/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java @@ -53,6 +53,8 @@ private void init() { @Autowired private ClinicalDataIntervalFilterApplier clinicalDataIntervalFilterApplier; @Autowired + private CustomDataFilterApplier customDataFilterApplier; + @Autowired private StudyViewFilterUtil studyViewFilterUtil; @Autowired private GeneService geneService; @@ -69,8 +71,6 @@ private void init() { @Autowired private StructuralVariantService structuralVariantService; @Autowired - private CustomDataFilterApplier customDataFilterApplier; - @Autowired private MolecularProfileUtil molecularProfileUtil; Function sampleToSampleIdentifier = new Function() { @@ -166,8 +166,39 @@ public List apply(StudyViewFilter studyViewFilter, Boolean neg molecularProfiles = molecularProfileService.getMolecularProfilesInStudies(studyIds, "SUMMARY"); } - sampleIdentifiers = intervalFilterExpressionData(sampleIdentifiers, molecularProfiles, - studyViewFilter.getGenomicDataFilters(), negateFilters); + List genomicDataEqualityFilters = new ArrayList<>(); + List genomicDataIntervalFilters = new ArrayList<>(); + + List genomicDataFilters = studyViewFilter.getGenomicDataFilters(); + + if (!CollectionUtils.isEmpty(genomicDataFilters)) { + Map molecularProfileMapByType = molecularProfileUtil + .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles) + .entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0))); + + genomicDataFilters.forEach(genomicDataFilter -> { + String profileType = genomicDataFilter.getProfileType(); + if (molecularProfileMapByType.containsKey(profileType)) { + if (molecularProfileMapByType.get(profileType).getDatatype().equals("DISCRETE")) { + genomicDataEqualityFilters.add(genomicDataFilter); + } else { + genomicDataIntervalFilters.add(genomicDataFilter); + } + } + }); + } + + if (!CollectionUtils.isEmpty(genomicDataEqualityFilters)) { + sampleIdentifiers = equalityFilterExpressionData(sampleIdentifiers, molecularProfiles, + genomicDataEqualityFilters, negateFilters); + } + + if (!CollectionUtils.isEmpty(genomicDataIntervalFilters)) { + sampleIdentifiers = intervalFilterExpressionData(sampleIdentifiers, molecularProfiles, + genomicDataIntervalFilters, negateFilters); + } sampleIdentifiers = intervalFilterExpressionData(sampleIdentifiers, molecularProfiles, studyViewFilter.getGenericAssayDataFilters(), negateFilters); @@ -296,6 +327,10 @@ private List equalityFilterClinicalData(List private List filterMutatedGenes(List mutatedGenefilters, Map molecularProfileMap, List sampleIdentifiers) { + if (sampleIdentifiers == null || sampleIdentifiers.isEmpty()) { + return new ArrayList<>(); + } + for (GeneFilter genefilter : mutatedGenefilters) { List filteredMolecularProfiles = genefilter @@ -364,6 +399,10 @@ private List filterMutatedGenes(List mutatedGenefi private List filterStructuralVariantGenes(List svGenefilters, Map molecularProfileMap, List sampleIdentifiers) { + + if (sampleIdentifiers == null || sampleIdentifiers.isEmpty()) { + return new ArrayList<>(); + } for (GeneFilter genefilter : svGenefilters) { @@ -433,6 +472,10 @@ private List filterStructuralVariantGenes(List svG private List filterCNAGenes(List cnaGeneFilters, Map molecularProfileMap, List sampleIdentifiers) { + + if (sampleIdentifiers == null || sampleIdentifiers.isEmpty()) { + return new ArrayList<>(); + } for (GeneFilter geneFilter : cnaGeneFilters) { @@ -568,16 +611,16 @@ public resultDataBins = new ArrayList<>(); + List resultDataBins; List filteredSampleIds = new ArrayList<>(); List filteredStudyIds = new ArrayList<>(); - List filteredData = fetchData(dataBinCountFilter, studyViewFilter, filteredSampleIds, + List filteredData = fetchData(dataBinCountFilter, studyViewFilter, filteredSampleIds, filteredStudyIds); List filteredUniqueSampleKeys = getUniqkeyKeys(filteredStudyIds, filteredSampleIds); - Map> filteredClinicalDataByAttributeId = filteredData.stream() - .collect(Collectors.groupingBy(ClinicalData::getAttrId)); + Map> filteredClinicalDataByAttributeId = filteredData.stream() + .collect(Collectors.groupingBy(Binnable::getAttrId)); if (dataBinMethod == DataBinMethod.STATIC) { @@ -589,15 +632,15 @@ public unfilteredSampleIds = new ArrayList<>(); List unfilteredStudyIds = new ArrayList<>(); - List unfilteredData = fetchData(dataBinCountFilter, filter, unfilteredSampleIds, + List unfilteredData = fetchData(dataBinCountFilter, filter, unfilteredSampleIds, unfilteredStudyIds); List unFilteredUniqueSampleKeys = getUniqkeyKeys(unfilteredSampleIds, unfilteredStudyIds); - Map> unfilteredDataByAttributeId = unfilteredData.stream() - .collect(Collectors.groupingBy(ClinicalData::getAttrId)); + Map> unfilteredDataByAttributeId = unfilteredData.stream() + .collect(Collectors.groupingBy(Binnable::getAttrId)); - resultDataBins = (List) dataBinFilters.stream().flatMap(dataBinFilter -> { + resultDataBins = dataBinFilters.stream().flatMap(dataBinFilter -> { String attributeId = getAttributeUniqueKey(dataBinFilter); return dataBinner .calculateClinicalDataBins(dataBinFilter, ClinicalDataType.SAMPLE, @@ -622,8 +665,12 @@ public List fetchData(S dataBinCountFilter, - StudyViewFilter studyViewFilter, List sampleIds, List studyIds) { + private List fetchData( + S dataBinCountFilter, + StudyViewFilter studyViewFilter, + List sampleIds, + List studyIds + ) { List filteredSampleIdentifiers = apply(studyViewFilter); studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); @@ -831,99 +878,39 @@ private GenericAssayDataBin dataBintoGenericAssayDataBin(GenericAssayDataBinFilt } public List intervalFilterExpressionData( - List sampleIdentifiers, List molecularProfiles, List dataFilters, - Boolean negateFilters) { - - if (!CollectionUtils.isEmpty(dataFilters) && !CollectionUtils.isEmpty(sampleIdentifiers)) { - - Map> molecularProfileMap = molecularProfileUtil - .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); + List sampleIdentifiers, List molecularProfiles, List dataFilters, + Boolean negateFilters) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - List clinicalDatas = new ArrayList<>(); - List attributes = new ArrayList<>(); - if (dataFilters.get(0) instanceof GenomicDataFilter) { - List genomicDataIntervalFilters = (List) dataFilters; - Set hugoGeneSymbols = genomicDataIntervalFilters.stream() - .map(GenomicDataFilter::getHugoGeneSymbol).collect(Collectors.toSet()); - Map geneNameIdMap = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(), - Projection.SUMMARY.name()) - .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); - - clinicalDatas = genomicDataIntervalFilters.stream().flatMap(genomicDataFilter -> { - - Map studyIdToMolecularProfileIdMap = molecularProfileMap - .getOrDefault(genomicDataFilter.getProfileType(), new ArrayList<>()) - .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, - MolecularProfile::getStableId)); - - GenomicDataBinFilter genomicDataBinFilter = new GenomicDataBinFilter(); - genomicDataBinFilter.setHugoGeneSymbol(genomicDataFilter.getHugoGeneSymbol()); - genomicDataBinFilter.setProfileType(genomicDataFilter.getProfileType()); - return invokeDataFunc(sampleIds, studyIds, - Arrays.asList(geneNameIdMap.get(genomicDataFilter.getHugoGeneSymbol()).toString()), - studyIdToMolecularProfileIdMap, genomicDataBinFilter, fetchMolecularData); - }).collect(Collectors.toList()); - - attributes = genomicDataIntervalFilters.stream().map(genomicDataIntervalFilter -> { - String attributeId = studyViewFilterUtil.getGenomicDataFilterUniqueKey( - genomicDataIntervalFilter.getHugoGeneSymbol(), genomicDataIntervalFilter.getProfileType()); - ClinicalDataFilter clinicalDataIntervalFilter = new ClinicalDataFilter(); - clinicalDataIntervalFilter.setAttributeId(attributeId); - clinicalDataIntervalFilter.setValues(genomicDataIntervalFilter.getValues()); - return clinicalDataIntervalFilter; - }).collect(Collectors.toList()); - } else { - List genericAssayDataFilters = (List) dataFilters; - - clinicalDatas = genericAssayDataFilters.stream().flatMap(genericAssayDataFilter -> { + return filterExpressionData(sampleIdentifiers, molecularProfiles, dataFilters, negateFilters, clinicalDataIntervalFilterApplier); + } - Map studyIdToMolecularProfileIdMap = molecularProfileMap - .getOrDefault(genericAssayDataFilter.getProfileType(), new ArrayList()) - .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, - MolecularProfile::getStableId)); - GenericAssayDataBinFilter genericAssayDataBinFilter = new GenericAssayDataBinFilter(); - genericAssayDataBinFilter.setStableId(genericAssayDataFilter.getStableId()); - genericAssayDataBinFilter.setProfileType(genericAssayDataFilter.getProfileType()); + public List equalityFilterExpressionData( + List sampleIdentifiers, List molecularProfiles, List dataFilters, + Boolean negateFilters) { - // get original data stream from invokeDataFunc - Stream dataStream = invokeDataFunc(sampleIds, studyIds, Arrays.asList(genericAssayDataBinFilter.getStableId()), - studyIdToMolecularProfileIdMap, genericAssayDataBinFilter, fetchGenericAssayData); - // For patient level generic assay profile, only keep the one sample per patient - List profiles = molecularProfileMap.getOrDefault(genericAssayDataFilter.getProfileType(), new ArrayList()); - if (profiles.size() > 0 && profiles.get(0).getPatientLevel() == true) { - dataStream = dataStream.collect(Collectors.groupingBy(d -> d.getPatientId())).values().stream() - .flatMap(d -> d.stream().limit(1)); - } - // don't change anything for non patient level data - return dataStream; - }).collect(Collectors.toList()); + return filterExpressionData(sampleIdentifiers, molecularProfiles, dataFilters, negateFilters, clinicalDataEqualityFilterApplier); + } - attributes = genericAssayDataFilters.stream().map(genericAssayDataFilter -> { - String attributeId = studyViewFilterUtil.getGenericAssayDataFilterUniqueKey( - genericAssayDataFilter.getStableId(), genericAssayDataFilter.getProfileType()); - ClinicalDataFilter clinicalDataIntervalFilter = new ClinicalDataFilter(); - clinicalDataIntervalFilter.setAttributeId(attributeId); - clinicalDataIntervalFilter.setValues(genericAssayDataFilter.getValues()); - return clinicalDataIntervalFilter; - }).collect(Collectors.toList()); - } + public List filterExpressionData( + List sampleIdentifiers, List molecularProfiles, List dataFilters, + Boolean negateFilters, ClinicalDataFilterApplier clinicalDataFilterApplier) { + if (!CollectionUtils.isEmpty(dataFilters) && !CollectionUtils.isEmpty(sampleIdentifiers)) { + List clinicalDatas = + fetchDataAndTransformToClinicalDataList(sampleIdentifiers, molecularProfiles, dataFilters); + List attributes =transformToClinicalDataFilter(dataFilters); MultiKeyMap clinicalDataMap = new MultiKeyMap(); clinicalDatas.forEach(clinicalData -> { clinicalDataMap.put(clinicalData.getStudyId(), clinicalData.getSampleId(), clinicalData.getAttrId(), - clinicalData.getAttrValue()); + clinicalData.getAttrValue()); }); List newSampleIdentifiers = new ArrayList<>(); for (SampleIdentifier sampleIdentifier : sampleIdentifiers) { - int count = clinicalDataIntervalFilterApplier.apply(attributes, clinicalDataMap, - sampleIdentifier.getSampleId(), sampleIdentifier.getStudyId(), negateFilters); + int count = clinicalDataFilterApplier.apply(attributes, clinicalDataMap, + sampleIdentifier.getSampleId(), sampleIdentifier.getStudyId(), negateFilters); if (count == attributes.size()) { newSampleIdentifiers.add(sampleIdentifier); @@ -935,4 +922,86 @@ public List intervalFilterExpressionDat return sampleIdentifiers; } + + private List fetchDataAndTransformToClinicalDataList( + List sampleIdentifiers, List molecularProfiles, List dataFilters) { + Map> molecularProfileMap = molecularProfileUtil + .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + if (dataFilters.get(0) instanceof GenomicDataFilter) { + List genomicDataIntervalFilters = (List) dataFilters; + Set hugoGeneSymbols = genomicDataIntervalFilters.stream() + .map(GenomicDataFilter::getHugoGeneSymbol).collect(Collectors.toSet()); + Map geneNameIdMap = geneService + .fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + return genomicDataIntervalFilters.stream().flatMap(genomicDataFilter -> { + + Map studyIdToMolecularProfileIdMap = molecularProfileMap + .getOrDefault(genomicDataFilter.getProfileType(), new ArrayList<>()) + .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, + MolecularProfile::getStableId)); + + GenomicDataBinFilter genomicDataBinFilter = new GenomicDataBinFilter(); + genomicDataBinFilter.setHugoGeneSymbol(genomicDataFilter.getHugoGeneSymbol()); + genomicDataBinFilter.setProfileType(genomicDataFilter.getProfileType()); + return invokeDataFunc(sampleIds, studyIds, + Collections.singletonList(geneNameIdMap.get(genomicDataFilter.getHugoGeneSymbol()).toString()), + studyIdToMolecularProfileIdMap, genomicDataBinFilter, fetchMolecularData); + }).collect(Collectors.toList()); + + } else { + + return ((List) dataFilters).stream().flatMap(genericAssayDataFilter -> { + + Map studyIdToMolecularProfileIdMap = molecularProfileMap + .getOrDefault(genericAssayDataFilter.getProfileType(), new ArrayList()) + .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, + MolecularProfile::getStableId)); + GenericAssayDataBinFilter genericAssayDataBinFilter = new GenericAssayDataBinFilter(); + genericAssayDataBinFilter.setStableId(genericAssayDataFilter.getStableId()); + genericAssayDataBinFilter.setProfileType(genericAssayDataFilter.getProfileType()); + + // get original data stream from invokeDataFunc + Stream dataStream = invokeDataFunc(sampleIds, studyIds, Collections.singletonList(genericAssayDataBinFilter.getStableId()), + studyIdToMolecularProfileIdMap, genericAssayDataBinFilter, fetchGenericAssayData); + // For patient level generic assay profile, only keep the one sample per patient + List profiles = molecularProfileMap.getOrDefault(genericAssayDataFilter.getProfileType(), new ArrayList<>()); + if (profiles.size() > 0 && profiles.get(0).getPatientLevel()) { + dataStream = dataStream.collect(Collectors.groupingBy(ClinicalData::getPatientId)).values().stream() + .flatMap(d -> d.stream().limit(1)); + } + // don't change anything for non patient level data + return dataStream; + }).collect(Collectors.toList()); + + } + } + + private List transformToClinicalDataFilter(List dataFilters) { + List attributes; + attributes = dataFilters.stream().map(dataFilter -> { + String attributeId; + if (dataFilter instanceof GenomicDataFilter) { + GenomicDataFilter genomicDataFilter = (GenomicDataFilter) dataFilter; + attributeId = studyViewFilterUtil.getGenomicDataFilterUniqueKey(genomicDataFilter.getHugoGeneSymbol(), genomicDataFilter.getProfileType()); + } else { + GenericAssayDataFilter genericAssayDataFilter = (GenericAssayDataFilter) dataFilter; + attributeId = studyViewFilterUtil.getGenericAssayDataFilterUniqueKey( + genericAssayDataFilter.getStableId(), genericAssayDataFilter.getProfileType()); + } + + ClinicalDataFilter clinicalDataFilter = new ClinicalDataFilter(); + clinicalDataFilter.setAttributeId(attributeId); + clinicalDataFilter.setValues(dataFilter.getValues()); + return clinicalDataFilter; + }).collect(Collectors.toList()); + return attributes; + } } diff --git a/web/src/main/java/org/cbioportal/web/util/StudyViewFilterUtil.java b/web/src/main/java/org/cbioportal/web/util/StudyViewFilterUtil.java index c6d7cbb3538..ecf5bdab85c 100644 --- a/web/src/main/java/org/cbioportal/web/util/StudyViewFilterUtil.java +++ b/web/src/main/java/org/cbioportal/web/util/StudyViewFilterUtil.java @@ -2,17 +2,24 @@ import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.map.MultiKeyMap; -import org.cbioportal.model.ClinicalData; +import org.cbioportal.model.Binnable; import org.cbioportal.model.ClinicalDataBin; import org.cbioportal.model.ClinicalDataCount; import org.cbioportal.model.ClinicalDataCountItem; import org.cbioportal.model.DataBin; -import org.cbioportal.model.MolecularProfile; +import org.cbioportal.model.Gene; +import org.cbioportal.model.GeneFilterQuery; import org.cbioportal.model.Patient; import org.cbioportal.model.SampleList; +import org.cbioportal.model.StructuralVariantFilterQuery; +import org.cbioportal.model.StructuralVariantSpecialValue; +import org.cbioportal.service.GeneService; +import org.cbioportal.service.util.CustomDataSession; +import org.cbioportal.service.util.CustomDataValue; import org.cbioportal.service.util.MolecularProfileUtil; import org.cbioportal.web.parameter.*; import org.springframework.beans.factory.annotation.Autowired; @@ -22,8 +29,15 @@ public class StudyViewFilterUtil { @Autowired private MolecularProfileUtil molecularProfileUtil; + + @Autowired + private GeneService geneService; - public void extractStudyAndSampleIds(List sampleIdentifiers, List studyIds, List sampleIds) { + public void extractStudyAndSampleIds( + List sampleIdentifiers, + List studyIds, + List sampleIds + ) { for (SampleIdentifier sampleIdentifier : sampleIdentifiers) { studyIds.add(sampleIdentifier.getStudyId()); sampleIds.add(sampleIdentifier.getSampleId()); @@ -31,19 +45,27 @@ public void extractStudyAndSampleIds(List sampleIdentifiers, L } public void removeSelfFromFilter(String attributeId, StudyViewFilter studyViewFilter) { - if (studyViewFilter!= null && studyViewFilter.getClinicalDataFilters() != null) { + if (studyViewFilter != null && studyViewFilter.getClinicalDataFilters() != null) { studyViewFilter.getClinicalDataFilters().removeIf(f -> f.getAttributeId().equals(attributeId)); } } + + public void removeSelfFromGenomicDataFilter(String hugoGeneSymbol, String profileType, StudyViewFilter studyViewFilter) { + if (studyViewFilter != null && studyViewFilter.getGenomicDataFilters() != null) { + studyViewFilter.getGenomicDataFilters().removeIf(f -> + f.getHugoGeneSymbol().equals(hugoGeneSymbol) && f.getProfileType().equals(profileType) + ); + } + } public void removeSelfFromGenericAssayFilter(String stableId, StudyViewFilter studyViewFilter) { - if (studyViewFilter!= null && studyViewFilter.getGenericAssayDataFilters() != null) { + if (studyViewFilter != null && studyViewFilter.getGenericAssayDataFilters() != null) { studyViewFilter.getGenericAssayDataFilters().removeIf(f -> f.getStableId().equals(stableId)); } } public void removeSelfCustomDataFromFilter(String attributeId, StudyViewFilter studyViewFilter) { - if (studyViewFilter!= null && studyViewFilter.getCustomDataFilters() != null) { + if (studyViewFilter != null && studyViewFilter.getCustomDataFilters() != null) { studyViewFilter.getCustomDataFilters().removeIf(f -> f.getAttributeId().equals(attributeId)); } } @@ -103,7 +125,7 @@ public Integer getFilteredCountByDataEquality(List attribute return count; } - public List getClinicalDataCountsFromCustomData(List customDataSessions, + public List getClinicalDataCountsFromCustomData(Collection customDataSessions, Map filteredSamplesMap, List patients) { int totalSamplesCount = filteredSamplesMap.keySet().size(); int totalPatientsCount = patients.size(); @@ -111,10 +133,9 @@ public List getClinicalDataCountsFromCustomData(List { Map> groupedDatabyValue = customDataSession.getData().getData().stream() - .filter(datum -> { - return filteredSamplesMap - .containsKey(getCaseUniqueKey(datum.getStudyId(), datum.getSampleId())); - }).collect(Collectors.groupingBy(CustomDataValue::getValue)); + .filter(datum -> filteredSamplesMap + .containsKey(getCaseUniqueKey(datum.getStudyId(), datum.getSampleId())) + ).collect(Collectors.groupingBy(CustomDataValue::getValue)); ClinicalDataCountItem clinicalDataCountItem = new ClinicalDataCountItem(); clinicalDataCountItem.setAttributeId(customDataSession.getId()); @@ -188,10 +209,10 @@ public boolean shouldSkipFilterForClinicalDataBins(StudyViewFilter filter) { ); } - public List filterClinicalData( - List unfilteredClinicalDataForSamples, - List unfilteredClinicalDataForPatients, - List unfilteredClinicalDataForConflictingPatientAttributes, + public List filterClinicalData( + List unfilteredClinicalDataForSamples, + List unfilteredClinicalDataForPatients, + List unfilteredClinicalDataForConflictingPatientAttributes, List studyIds, List sampleIds, List studyIdsOfPatients, @@ -200,7 +221,7 @@ public List filterClinicalData( List patientAttributeIds, List conflictingPatientAttributes ) { - List combinedResult = new ArrayList<>(); + List combinedResult = new ArrayList<>(); Map patientIdToStudyId = null; @@ -250,9 +271,80 @@ public List filterClinicalData( return combinedResult; } - - private List filterClinicalDataByStudyAndSampleAndAttribute( - List clinicalData, + + public List cleanQueryGeneIds(List geneQueries) { + List hugoGeneSymbols = geneQueries + .stream() + .map(GeneFilterQuery::getHugoGeneSymbol) + .collect(Collectors.toList()); + + Map symbolToEntrezGeneId = getStringIntegerMap(hugoGeneSymbols); + + geneQueries.removeIf( + q -> !symbolToEntrezGeneId.containsKey(q.getHugoGeneSymbol()) + ); + + geneQueries.stream().forEach( + q -> q.setEntrezGeneId(symbolToEntrezGeneId.get(q.getHugoGeneSymbol())) + ); + + return geneQueries; + } + + private Map getStringIntegerMap(List hugoGeneSymbols) { + Map symbolToEntrezGeneId = geneService + .fetchGenes(new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), Projection.SUMMARY.name()) + .stream() + .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + return symbolToEntrezGeneId; + } + + public List resolveEntrezGeneIds(List structVarQueries) { + + List hugoGeneSymbols = structVarQueries + .stream() + .flatMap(q -> Stream.of(q.getGene1Query(), q.getGene2Query())) + .filter(structVarIdentifier -> structVarIdentifier.getHugoSymbol() != null) + .map(structVarIdentifier -> structVarIdentifier.getHugoSymbol()) + .collect(Collectors.toList()); + + Map symbolToEntrezGeneId = getStringIntegerMap(hugoGeneSymbols); + + // Add Entrez gene ids to the queries. + structVarQueries.forEach(structVarQuery -> { + structVarQuery.getGene1Query().setEntrezId( + symbolToEntrezGeneId.getOrDefault(structVarQuery.getGene1Query().getHugoSymbol(), null) + ); + structVarQuery.getGene2Query().setEntrezId( + symbolToEntrezGeneId.getOrDefault(structVarQuery.getGene2Query().getHugoSymbol(), null) + ); + }); + + // Remove any genes where the Entrez gene id is needed, but translation failed. + structVarQueries.removeIf( + q -> (q.getGene1Query().getSpecialValue() != StructuralVariantSpecialValue.NO_GENE + && q.getGene1Query().getSpecialValue() != StructuralVariantSpecialValue.ANY_GENE + && q.getGene1Query().getEntrezId() == null) + || (q.getGene2Query().getSpecialValue() != StructuralVariantSpecialValue.NO_GENE + && q.getGene2Query().getSpecialValue() != StructuralVariantSpecialValue.ANY_GENE + && q.getGene2Query().getEntrezId() == null) + ); + + return structVarQueries; + } + + private Map getHugoToEntrezQueryMap(List hugoGeneSymbols) { + Map symbolToEntrezGeneId = geneService + .fetchGenes(new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), Projection.SUMMARY.name()) + .stream() + .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + return symbolToEntrezGeneId; + } + + private List filterClinicalDataByStudyAndSampleAndAttribute( + List clinicalData, Map sampleToStudyId, Map attributeIdLookup ) { @@ -265,8 +357,8 @@ private List filterClinicalDataByStudyAndSampleAndAttribute( .collect(Collectors.toList()); } - private List filterClinicalDataByStudyAndPatientAndAttribute( - List clinicalData, + private List filterClinicalDataByStudyAndPatientAndAttribute( + List clinicalData, Map patientToStudyId, Map attributeIdLookup ) { @@ -296,15 +388,16 @@ private Map mapCaseToStudy(List caseIds, List s return caseToStudy; } - private String generateSampleToStudyKey(ClinicalData clinicalData) { + private String generateSampleToStudyKey(Binnable clinicalData) { return generateCaseToStudyKey(clinicalData.getStudyId(), clinicalData.getSampleId()); } - private String generatePatientToStudyKey(ClinicalData clinicalData) { + private String generatePatientToStudyKey(Binnable clinicalData) { return generateCaseToStudyKey(clinicalData.getStudyId(), clinicalData.getPatientId()); } private String generateCaseToStudyKey(String studyId, String caseId) { return studyId + ":" + caseId; } + } diff --git a/web/src/main/java/org/cbioportal/web/util/appliers/AbstractPatientTreatmentFilter.java b/web/src/main/java/org/cbioportal/web/util/appliers/AbstractPatientTreatmentFilter.java index 81e7a003315..30d507d297a 100644 --- a/web/src/main/java/org/cbioportal/web/util/appliers/AbstractPatientTreatmentFilter.java +++ b/web/src/main/java/org/cbioportal/web/util/appliers/AbstractPatientTreatmentFilter.java @@ -8,6 +8,7 @@ import org.cbioportal.web.parameter.filter.AndedPatientTreatmentFilters; import org.springframework.beans.factory.annotation.Autowired; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; @@ -25,6 +26,11 @@ public List filter( List identifiers, StudyViewFilter filter ) { + + if (identifiers == null || identifiers.isEmpty()) { + return new ArrayList<>(); + } + AndedPatientTreatmentFilters filters = getFilters(filter); List sampleIds = identifiers.stream() diff --git a/web/src/main/java/org/cbioportal/web/util/appliers/AbstractSampleTreatmentFilter.java b/web/src/main/java/org/cbioportal/web/util/appliers/AbstractSampleTreatmentFilter.java index 302197c7ee4..c28dcefbcbd 100644 --- a/web/src/main/java/org/cbioportal/web/util/appliers/AbstractSampleTreatmentFilter.java +++ b/web/src/main/java/org/cbioportal/web/util/appliers/AbstractSampleTreatmentFilter.java @@ -8,6 +8,7 @@ import org.cbioportal.web.parameter.filter.AndedSampleTreatmentFilters; import org.springframework.beans.factory.annotation.Autowired; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; @@ -25,6 +26,11 @@ public List filter ( List identifiers, StudyViewFilter filter ) { + + if (identifiers == null || identifiers.isEmpty()) { + return new ArrayList<>(); + } + AndedSampleTreatmentFilters filters = getFilters(filter); List sampleIds = identifiers.stream() diff --git a/web/src/main/java/org/cbioportal/web/util/appliers/ClinicalEventFilterApplier.java b/web/src/main/java/org/cbioportal/web/util/appliers/ClinicalEventFilterApplier.java index 53614a4ca73..adf70d4a782 100644 --- a/web/src/main/java/org/cbioportal/web/util/appliers/ClinicalEventFilterApplier.java +++ b/web/src/main/java/org/cbioportal/web/util/appliers/ClinicalEventFilterApplier.java @@ -9,6 +9,7 @@ import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -25,7 +26,11 @@ public final class ClinicalEventFilterApplier implements StudyViewSubFilterAppli @Override public List filter(@NonNull List toFilter, @NonNull StudyViewFilter filters) { - + + if (toFilter == null || toFilter.isEmpty()) { + return new ArrayList<>(); + } + List studyIds = toFilter.stream() .map(SampleIdentifier::getStudyId) .collect(Collectors.toList()); diff --git a/web/src/main/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplier.java b/web/src/main/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplier.java new file mode 100644 index 00000000000..9367c54884b --- /dev/null +++ b/web/src/main/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplier.java @@ -0,0 +1,112 @@ +package org.cbioportal.web.util.appliers; + +import org.cbioportal.model.MolecularProfile; +import org.cbioportal.model.StructuralVariantFilterQuery; +import org.cbioportal.model.StudyViewStructuralVariantFilter; +import org.cbioportal.service.MolecularProfileService; +import org.cbioportal.service.StructuralVariantService; +import org.cbioportal.web.parameter.SampleIdentifier; +import org.cbioportal.web.parameter.StudyViewFilter; +import org.cbioportal.web.util.StudyViewFilterUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Component +public class StructuralVariantSubFilterApplier implements StudyViewSubFilterApplier { + + @Autowired + private MolecularProfileService molecularProfileService; + + @Autowired + private StructuralVariantService structuralVariantService; + + @Autowired + private StudyViewFilterUtil studyViewFilterUtil; + + @Override + public List filter(List toFilter, StudyViewFilter filters) { + + final List structVarFilters = getStructVarFilters(filters); + + List includedStudyIds = toFilter.stream() + .map(SampleIdentifier::getStudyId) + .distinct() + .collect(Collectors.toList()); + + List molecularProfiles = molecularProfileService.getMolecularProfilesInStudies(includedStudyIds, "SUMMARY"); + + Map molecularProfileMap = molecularProfiles.stream() + .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); + + List remainingSampleIdentifiers = toFilter; + + for (StudyViewStructuralVariantFilter structuralVariantFilter : structVarFilters) { + + // Collect molecular profiles referenced in gene filter. + List filteredMolecularProfiles = structuralVariantFilter + .getMolecularProfileIds() + .stream() + .map(molecularProfileId -> molecularProfileMap.get(molecularProfileId)) + .collect(Collectors.toList()); + + Map> mapByStudyId = filteredMolecularProfiles + .stream() + .collect(Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); + + for (List structVarQueries: structuralVariantFilter.getStructVarQueries()) { + + // Remove samples in remainingSampleIdentifiers that belong to a study that is not accessible to the current user + // (do not appear in the molecularProfileMap argument). + final List filteredSampleIdentifiers = remainingSampleIdentifiers.stream() + .filter(i -> mapByStudyId.containsKey(i.getStudyId())).collect(Collectors.toList()); + + final List molecularProfileIds = filteredSampleIdentifiers.stream() + .map(i -> mapByStudyId.get(i.getStudyId()).get(0).getStableId()) + .distinct() + .collect(Collectors.toList()); + + final List sampleIds = filteredSampleIdentifiers.stream() + .map(SampleIdentifier::getSampleId) + .collect(Collectors.toList()); + + final List entrezIdEnhancedSvQueries = studyViewFilterUtil.resolveEntrezGeneIds(structVarQueries); + remainingSampleIdentifiers = structuralVariantService + .fetchStructuralVariantsByStructVarQueries(molecularProfileIds, sampleIds, entrezIdEnhancedSvQueries) + .stream() + .map(m -> { + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(m.getSampleId()); + sampleIdentifier.setStudyId(m.getStudyId()); + return sampleIdentifier; + }) + .distinct() + .collect(Collectors.toList()); + } + + } + return remainingSampleIdentifiers; + } + + @Override + public boolean shouldApplyFilter(StudyViewFilter studyViewFilter) { + return !getStructVarFilters(studyViewFilter).isEmpty(); + } + + private static List getStructVarFilters(StudyViewFilter filters) { + final List structuralVariantFilters = filters.getStructuralVariantFilters(); + if (structuralVariantFilters == null || structuralVariantFilters.isEmpty()) { + return new ArrayList<>(); + } + final List structVarFilters = structuralVariantFilters.stream() + .filter(structuralVariantFilter -> !structuralVariantFilter.getStructVarQueries().isEmpty()) + .collect(Collectors.toList()); + return structVarFilters; + } + +} diff --git a/web/src/test/java/org/cbioportal/web/ClinicalDataEnrichmentControllerTest.java b/web/src/test/java/org/cbioportal/web/ClinicalDataEnrichmentControllerTest.java index 0399d1097fc..bb9c9333476 100644 --- a/web/src/test/java/org/cbioportal/web/ClinicalDataEnrichmentControllerTest.java +++ b/web/src/test/java/org/cbioportal/web/ClinicalDataEnrichmentControllerTest.java @@ -37,7 +37,7 @@ @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@ContextConfiguration("/applicationContext-web.xml") +@ContextConfiguration("/applicationContext-web-test.xml") @Configuration public class ClinicalDataEnrichmentControllerTest { diff --git a/web/src/test/java/org/cbioportal/web/DataAccessTokenControllerTest.java b/web/src/test/java/org/cbioportal/web/DataAccessTokenControllerTest.java index e429756295a..b7155e59921 100644 --- a/web/src/test/java/org/cbioportal/web/DataAccessTokenControllerTest.java +++ b/web/src/test/java/org/cbioportal/web/DataAccessTokenControllerTest.java @@ -37,6 +37,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -47,7 +48,7 @@ import javax.servlet.http.HttpSession; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations={"/applicationContext-web.xml", "/applicationContext-security-test.xml"}) +@ContextConfiguration(locations={"/applicationContext-web-test.xml", "/applicationContext-security-test.xml"}) @WebAppConfiguration public class DataAccessTokenControllerTest { @@ -190,6 +191,32 @@ public void createTokenValidUserTest() throws Exception { .andReturn(); } + @Test + public void createTokenValidUserTestWithUserRole() throws Exception { + ReflectionTestUtils.setField(DataAccessTokenController.class, "userRoleToAccessToken", "PLACEHOLDER_ROLE"); + Mockito.when(tokenService.createDataAccessToken(ArgumentMatchers.anyString())).thenReturn(MOCK_TOKEN_INFO); + HttpSession session = getSession(MOCK_USER, MOCK_PASSWORD); + MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/data-access-tokens") + .session((MockHttpSession) session) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isCreated()) + .andReturn(); + } + + @Test + public void createTokenUnauthorizedUserTestWithUserRole() throws Exception { + ReflectionTestUtils.setField(DataAccessTokenController.class, "userRoleToAccessToken", "TEST"); + Mockito.when(tokenService.createDataAccessToken(ArgumentMatchers.anyString())).thenReturn(MOCK_TOKEN_INFO); + HttpSession session = getSession(MOCK_USER, MOCK_PASSWORD); + MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/data-access-tokens") + .session((MockHttpSession) session) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isUnauthorized()) + .andReturn(); + } + /* Tests mapping for DELETE /data-access-tokens * Checks response status code is 200 success * Checks that correct username argument is passed to service class @@ -241,4 +268,14 @@ public Void answer(InvocationOnMock getAllTokensInvocation) { Assert.fail("Unexpected argument passed to service class. Expected argument: " + MOCK_USER + " Received argument: " + receivedArgument); } } + + @Test + public void createTokenNotLoggedIn() throws Exception { + Mockito.when(tokenService.createDataAccessToken(ArgumentMatchers.anyString())).thenReturn(MOCK_TOKEN_INFO); + MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/data-access-tokens") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isUnauthorized()) + .andReturn(); + } } diff --git a/web/src/test/java/org/cbioportal/web/ExpressionEnrichmentControllerTest.java b/web/src/test/java/org/cbioportal/web/ExpressionEnrichmentControllerTest.java index 868b46cfa06..0abe4a9e3ca 100644 --- a/web/src/test/java/org/cbioportal/web/ExpressionEnrichmentControllerTest.java +++ b/web/src/test/java/org/cbioportal/web/ExpressionEnrichmentControllerTest.java @@ -186,7 +186,7 @@ public void fetchGenericAssayEnrichments() throws Exception { genericAssayEnrichment2.setpValue(TEST_P_VALUE_2); genericAssayEnrichments.add(genericAssayEnrichment2); - Mockito.when(expressionEnrichmentService.getGenericAssayEnrichments(Mockito.anyString(), Mockito.anyMap(), + Mockito.when(expressionEnrichmentService.getGenericAssayNumericalEnrichments(Mockito.anyString(), Mockito.anyMap(), Mockito.any(EnrichmentType.class))).thenReturn(genericAssayEnrichments); mockMvc.perform(MockMvcRequestBuilders.post("/generic-assay-enrichments/fetch") diff --git a/web/src/test/java/org/cbioportal/web/GenericAssayControllerTest.java b/web/src/test/java/org/cbioportal/web/GenericAssayControllerTest.java index c8bf31069ae..92aeaa55f12 100644 --- a/web/src/test/java/org/cbioportal/web/GenericAssayControllerTest.java +++ b/web/src/test/java/org/cbioportal/web/GenericAssayControllerTest.java @@ -34,7 +34,7 @@ @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@ContextConfiguration("/applicationContext-web.xml") +@ContextConfiguration("/applicationContext-web-test.xml") @Configuration public class GenericAssayControllerTest { diff --git a/web/src/test/java/org/cbioportal/web/GenericAssayDataControllerTest.java b/web/src/test/java/org/cbioportal/web/GenericAssayDataControllerTest.java index 20dedf7ebfa..be24576b747 100644 --- a/web/src/test/java/org/cbioportal/web/GenericAssayDataControllerTest.java +++ b/web/src/test/java/org/cbioportal/web/GenericAssayDataControllerTest.java @@ -33,7 +33,7 @@ @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@ContextConfiguration("/applicationContext-web.xml") +@ContextConfiguration("/applicationContext-web-test.xml") @Configuration public class GenericAssayDataControllerTest { diff --git a/web/src/test/java/org/cbioportal/web/MutationControllerTest.java b/web/src/test/java/org/cbioportal/web/MutationControllerTest.java index da622a1c6fc..7f9018d0e85 100644 --- a/web/src/test/java/org/cbioportal/web/MutationControllerTest.java +++ b/web/src/test/java/org/cbioportal/web/MutationControllerTest.java @@ -30,7 +30,6 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @@ -58,16 +57,11 @@ public class MutationControllerTest { private static final String TEST_TUMOR_SEQ_ALLELE_1 = "test_tumor_seq_allele_1"; private static final String TEST_PROTEIN_CHANGE_1 = "test_protein_change_1"; private static final String TEST_MUTATION_TYPE_1 = "test_mutation_type_1"; - private static final String TEST_FUNCTIONAL_IMPACT_SCORE_1 = "test_functional_impact_score_1"; - private static final BigDecimal TEST_FIS_VALUE_1 = new BigDecimal(0.1); - private static final String TEST_LINK_XVAR_1 = "test_link_xvar_1"; - private static final String TEST_LINK_PDB_1 = "test_link_pdb_1"; - private static final String TEST_LINK_MSA_1 = "test_link_msa_1"; private static final String TEST_NCBI_BUILD_1 = "test_ncbi_build_1"; private static final String TEST_VARIANT_TYPE_1 = "test_variant_type_1"; - private static final String TEST_ONCOTATOR_REFSEQ_MRNA_ID_1 = "test_oncotator_refseq_mrna_id_1"; - private static final int TEST_ONCOTATOR_PROTEIN_POS_START_1 = 1; - private static final int TEST_ONCOTATOR_PROTEIN_POS_END_1 = 1; + private static final String TEST_MUTATION_REFSEQ_MRNA_ID_1 = "test_mutation_refseq_mrna_id_1"; + private static final int TEST_MUTATION_PROTEIN_POS_START_1 = 1; + private static final int TEST_MUTATION_PROTEIN_POS_END_1 = 1; private static final String TEST_KEYWORD_1 = "test_keyword_1"; private static final String TEST_HUGO_GENE_SYMBOL_1 = "test_hugo_gene_symbol_1"; private static final String TEST_TYPE_1 = "test_type_1"; @@ -100,16 +94,11 @@ public class MutationControllerTest { private static final String TEST_TUMOR_SEQ_ALLELE_2 = "test_tumor_seq_allele_2"; private static final String TEST_PROTEIN_CHANGE_2 = "test_protein_change_2"; private static final String TEST_MUTATION_TYPE_2 = "test_mutation_type_2"; - private static final String TEST_FUNCTIONAL_IMPACT_SCORE_2 = "test_functional_impact_score_2"; - private static final BigDecimal TEST_FIS_VALUE_2 = new BigDecimal(0.2); - private static final String TEST_LINK_XVAR_2 = "test_link_xvar_2"; - private static final String TEST_LINK_PDB_2 = "test_link_pdb_2"; - private static final String TEST_LINK_MSA_2 = "test_link_msa_2"; private static final String TEST_NCBI_BUILD_2 = "test_ncbi_build_2"; private static final String TEST_VARIANT_TYPE_2 = "test_variant_type_2"; - private static final String TEST_ONCOTATOR_REFSEQ_MRNA_ID_2 = "test_oncotator_refseq_mrna_id_2"; - private static final int TEST_ONCOTATOR_PROTEIN_POS_START_2 = 2; - private static final int TEST_ONCOTATOR_PROTEIN_POS_END_2 = 2; + private static final String TEST_MUTATION_REFSEQ_MRNA_ID_2 = "test_MUTATION_refseq_mrna_id_2"; + private static final int TEST_MUTATION_PROTEIN_POS_START_2 = 2; + private static final int TEST_MUTATION_PROTEIN_POS_END_2 = 2; private static final String TEST_KEYWORD_2 = "test_keyword_2"; private static final String TEST_HUGO_GENE_SYMBOL_2 = "test_hugo_gene_symbol_2"; private static final String TEST_TYPE_2 = "test_type_2"; @@ -195,17 +184,11 @@ public void getMutationsInMolecularProfileBySampleListIdDefaultProjection() thro .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilterAnnotation").value(TEST_DRIVER_FILTER_ANNOTATION_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter").value(TEST_DRIVER_TIERS_FILTER_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnnotation").value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].functionalImpactScore") - .value(TEST_FUNCTIONAL_IMPACT_SCORE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].fisValue").value(TEST_FIS_VALUE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkXvar").value(TEST_LINK_XVAR_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkPdb").value(TEST_LINK_PDB_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkMsa").value(TEST_LINK_MSA_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantType").value(TEST_VARIANT_TYPE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId").value(TEST_ONCOTATOR_REFSEQ_MRNA_ID_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId").value(TEST_MUTATION_REFSEQ_MRNA_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene").doesNotExist()) .andExpect(MockMvcResultMatchers.jsonPath("$[0].namespaceColumns.columnName.fieldName").value("fieldValue")) @@ -231,17 +214,11 @@ public void getMutationsInMolecularProfileBySampleListIdDefaultProjection() thro .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverFilterAnnotation").value(TEST_DRIVER_FILTER_ANNOTATION_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverTiersFilter").value(TEST_DRIVER_TIERS_FILTER_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverTiersFilterAnnotation").value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].functionalImpactScore") - .value(TEST_FUNCTIONAL_IMPACT_SCORE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].fisValue").value(TEST_FIS_VALUE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkXvar").value(TEST_LINK_XVAR_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkPdb").value(TEST_LINK_PDB_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkMsa").value(TEST_LINK_MSA_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].ncbiBuild").value(TEST_NCBI_BUILD_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].variantType").value(TEST_VARIANT_TYPE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId").value(TEST_ONCOTATOR_REFSEQ_MRNA_ID_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId").value(TEST_MUTATION_REFSEQ_MRNA_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene").doesNotExist()) .andExpect(MockMvcResultMatchers.jsonPath("$[1].namespaceColumns.columnName.fieldName").value("fieldValue")); @@ -285,17 +262,11 @@ public void getMutationsInMolecularProfileBySampleListIdDetailedProjection() thr .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilterAnnotation").value(TEST_DRIVER_FILTER_ANNOTATION_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter").value(TEST_DRIVER_TIERS_FILTER_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnnotation").value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].functionalImpactScore") - .value(TEST_FUNCTIONAL_IMPACT_SCORE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].fisValue").value(TEST_FIS_VALUE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkXvar").value(TEST_LINK_XVAR_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkPdb").value(TEST_LINK_PDB_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkMsa").value(TEST_LINK_MSA_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantType").value(TEST_VARIANT_TYPE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId").value(TEST_ONCOTATOR_REFSEQ_MRNA_ID_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId").value(TEST_MUTATION_REFSEQ_MRNA_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene.hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) @@ -329,17 +300,11 @@ public void getMutationsInMolecularProfileBySampleListIdDetailedProjection() thr .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverFilterAnnotation").value(TEST_DRIVER_FILTER_ANNOTATION_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverTiersFilter").value(TEST_DRIVER_TIERS_FILTER_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverTiersFilterAnnotation").value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].functionalImpactScore") - .value(TEST_FUNCTIONAL_IMPACT_SCORE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].fisValue").value(TEST_FIS_VALUE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkXvar").value(TEST_LINK_XVAR_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkPdb").value(TEST_LINK_PDB_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkMsa").value(TEST_LINK_MSA_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].ncbiBuild").value(TEST_NCBI_BUILD_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].variantType").value(TEST_VARIANT_TYPE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId").value(TEST_ONCOTATOR_REFSEQ_MRNA_ID_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId").value(TEST_MUTATION_REFSEQ_MRNA_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene.hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) @@ -422,17 +387,11 @@ public void fetchMutationsInMultipleMolecularProfiles() throws Exception { .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilterAnnotation").value(TEST_DRIVER_FILTER_ANNOTATION_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter").value(TEST_DRIVER_TIERS_FILTER_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnnotation").value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].functionalImpactScore") - .value(TEST_FUNCTIONAL_IMPACT_SCORE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].fisValue").value(TEST_FIS_VALUE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkXvar").value(TEST_LINK_XVAR_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkPdb").value(TEST_LINK_PDB_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkMsa").value(TEST_LINK_MSA_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantType").value(TEST_VARIANT_TYPE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId").value(TEST_ONCOTATOR_REFSEQ_MRNA_ID_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId").value(TEST_MUTATION_REFSEQ_MRNA_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene").doesNotExist()) .andExpect(MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") @@ -457,17 +416,11 @@ public void fetchMutationsInMultipleMolecularProfiles() throws Exception { .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverFilterAnnotation").value(TEST_DRIVER_FILTER_ANNOTATION_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverTiersFilter").value(TEST_DRIVER_TIERS_FILTER_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverTiersFilterAnnotation").value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].functionalImpactScore") - .value(TEST_FUNCTIONAL_IMPACT_SCORE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].fisValue").value(TEST_FIS_VALUE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkXvar").value(TEST_LINK_XVAR_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkPdb").value(TEST_LINK_PDB_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkMsa").value(TEST_LINK_MSA_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].ncbiBuild").value(TEST_NCBI_BUILD_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].variantType").value(TEST_VARIANT_TYPE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId").value(TEST_ONCOTATOR_REFSEQ_MRNA_ID_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId").value(TEST_MUTATION_REFSEQ_MRNA_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene").doesNotExist()); } @@ -517,17 +470,11 @@ public void fetchMutationsInMolecularProfileDefaultProjection() throws Exception .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilterAnnotation").value(TEST_DRIVER_FILTER_ANNOTATION_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter").value(TEST_DRIVER_TIERS_FILTER_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnnotation").value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].functionalImpactScore") - .value(TEST_FUNCTIONAL_IMPACT_SCORE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].fisValue").value(TEST_FIS_VALUE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkXvar").value(TEST_LINK_XVAR_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkPdb").value(TEST_LINK_PDB_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkMsa").value(TEST_LINK_MSA_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantType").value(TEST_VARIANT_TYPE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId").value(TEST_ONCOTATOR_REFSEQ_MRNA_ID_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId").value(TEST_MUTATION_REFSEQ_MRNA_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene").doesNotExist()) .andExpect(MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") @@ -552,17 +499,11 @@ public void fetchMutationsInMolecularProfileDefaultProjection() throws Exception .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverFilterAnnotation").value(TEST_DRIVER_FILTER_ANNOTATION_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverTiersFilter").value(TEST_DRIVER_TIERS_FILTER_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverTiersFilterAnnotation").value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].functionalImpactScore") - .value(TEST_FUNCTIONAL_IMPACT_SCORE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].fisValue").value(TEST_FIS_VALUE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkXvar").value(TEST_LINK_XVAR_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkPdb").value(TEST_LINK_PDB_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkMsa").value(TEST_LINK_MSA_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].ncbiBuild").value(TEST_NCBI_BUILD_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].variantType").value(TEST_VARIANT_TYPE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId").value(TEST_ONCOTATOR_REFSEQ_MRNA_ID_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId").value(TEST_MUTATION_REFSEQ_MRNA_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene").doesNotExist()); } @@ -613,17 +554,11 @@ public void fetchMutationsInMolecularProfileDetailedProjection() throws Exceptio .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilterAnnotation").value(TEST_DRIVER_FILTER_ANNOTATION_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter").value(TEST_DRIVER_TIERS_FILTER_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnnotation").value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].functionalImpactScore") - .value(TEST_FUNCTIONAL_IMPACT_SCORE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].fisValue").value(TEST_FIS_VALUE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkXvar").value(TEST_LINK_XVAR_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkPdb").value(TEST_LINK_PDB_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].linkMsa").value(TEST_LINK_MSA_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantType").value(TEST_VARIANT_TYPE_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId").value(TEST_ONCOTATOR_REFSEQ_MRNA_ID_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId").value(TEST_MUTATION_REFSEQ_MRNA_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene.hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) @@ -658,17 +593,11 @@ public void fetchMutationsInMolecularProfileDetailedProjection() throws Exceptio .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverFilterAnnotation").value(TEST_DRIVER_FILTER_ANNOTATION_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverTiersFilter").value(TEST_DRIVER_TIERS_FILTER_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverTiersFilterAnnotation").value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].functionalImpactScore") - .value(TEST_FUNCTIONAL_IMPACT_SCORE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].fisValue").value(TEST_FIS_VALUE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkXvar").value(TEST_LINK_XVAR_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkPdb").value(TEST_LINK_PDB_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].linkMsa").value(TEST_LINK_MSA_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].ncbiBuild").value(TEST_NCBI_BUILD_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].variantType").value(TEST_VARIANT_TYPE_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId").value(TEST_ONCOTATOR_REFSEQ_MRNA_ID_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId").value(TEST_MUTATION_REFSEQ_MRNA_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene.hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) @@ -714,14 +643,14 @@ public void fetchMutationCountsByPosition() throws Exception { List mutationCountByPositionList = new ArrayList<>(); MutationCountByPosition mutationCountByPosition1 = new MutationCountByPosition(); mutationCountByPosition1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); - mutationCountByPosition1.setProteinPosStart(TEST_ONCOTATOR_PROTEIN_POS_START_1); - mutationCountByPosition1.setProteinPosEnd(TEST_ONCOTATOR_PROTEIN_POS_END_1); + mutationCountByPosition1.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_1); + mutationCountByPosition1.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_1); mutationCountByPosition1.setCount(TEST_MUTATION_COUNT_1); mutationCountByPositionList.add(mutationCountByPosition1); MutationCountByPosition mutationCountByPosition2 = new MutationCountByPosition(); mutationCountByPosition2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); - mutationCountByPosition2.setProteinPosStart(TEST_ONCOTATOR_PROTEIN_POS_START_2); - mutationCountByPosition2.setProteinPosEnd(TEST_ONCOTATOR_PROTEIN_POS_END_2); + mutationCountByPosition2.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_2); + mutationCountByPosition2.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_2); mutationCountByPosition2.setCount(TEST_MUTATION_COUNT_2); mutationCountByPositionList.add(mutationCountByPosition2); @@ -732,13 +661,13 @@ public void fetchMutationCountsByPosition() throws Exception { List mutationPositionIdentifiers = new ArrayList<>(); MutationPositionIdentifier mutationPositionIdentifier1 = new MutationPositionIdentifier(); mutationPositionIdentifier1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); - mutationPositionIdentifier1.setProteinPosStart(TEST_ONCOTATOR_PROTEIN_POS_START_1); - mutationPositionIdentifier1.setProteinPosEnd(TEST_ONCOTATOR_PROTEIN_POS_END_1); + mutationPositionIdentifier1.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_1); + mutationPositionIdentifier1.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_1); mutationPositionIdentifiers.add(mutationPositionIdentifier1); MutationPositionIdentifier mutationPositionIdentifier2 = new MutationPositionIdentifier(); mutationPositionIdentifier2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); - mutationPositionIdentifier2.setProteinPosStart(TEST_ONCOTATOR_PROTEIN_POS_START_2); - mutationPositionIdentifier2.setProteinPosEnd(TEST_ONCOTATOR_PROTEIN_POS_END_2); + mutationPositionIdentifier2.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_2); + mutationPositionIdentifier2.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_2); mutationPositionIdentifiers.add(mutationPositionIdentifier2); mockMvc.perform(MockMvcRequestBuilders.post("/mutation-counts-by-position/fetch") @@ -749,12 +678,12 @@ public void fetchMutationCountsByPosition() throws Exception { .andExpect(MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_1)) - .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value(TEST_MUTATION_COUNT_1)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_ONCOTATOR_PROTEIN_POS_START_2)) - .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_ONCOTATOR_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosStart").value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd").value(TEST_MUTATION_PROTEIN_POS_END_2)) .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value(TEST_MUTATION_COUNT_2)); } @@ -783,16 +712,11 @@ private List createExampleMutations() { mutation1.setDriverFilterAnnotation(TEST_DRIVER_FILTER_ANNOTATION_1); mutation1.setDriverTiersFilter(TEST_DRIVER_TIERS_FILTER_1); mutation1.setDriverTiersFilterAnnotation(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1); - mutation1.setFunctionalImpactScore(TEST_FUNCTIONAL_IMPACT_SCORE_1); - mutation1.setFisValue(TEST_FIS_VALUE_1); - mutation1.setLinkXvar(TEST_LINK_XVAR_1); - mutation1.setLinkPdb(TEST_LINK_PDB_1); - mutation1.setLinkMsa(TEST_LINK_MSA_1); mutation1.setNcbiBuild(TEST_NCBI_BUILD_1); mutation1.setVariantType(TEST_VARIANT_TYPE_1); - mutation1.setOncotatorRefseqMrnaId(TEST_ONCOTATOR_REFSEQ_MRNA_ID_1); - mutation1.setOncotatorProteinPosStart(TEST_ONCOTATOR_PROTEIN_POS_START_1); - mutation1.setOncotatorProteinPosEnd(TEST_ONCOTATOR_PROTEIN_POS_END_1); + mutation1.setRefseqMrnaId(TEST_MUTATION_REFSEQ_MRNA_ID_1); + mutation1.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_1); + mutation1.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_1); mutation1.setKeyword(TEST_KEYWORD_1); mutation1.setAnnotationJSON(NAME_SPACE_COLUMNS); mutationList.add(mutation1); @@ -818,16 +742,11 @@ private List createExampleMutations() { mutation2.setDriverFilterAnnotation(TEST_DRIVER_FILTER_ANNOTATION_2); mutation2.setDriverTiersFilter(TEST_DRIVER_TIERS_FILTER_2); mutation2.setDriverTiersFilterAnnotation(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2); - mutation2.setFunctionalImpactScore(TEST_FUNCTIONAL_IMPACT_SCORE_2); - mutation2.setFisValue(TEST_FIS_VALUE_2); - mutation2.setLinkXvar(TEST_LINK_XVAR_2); - mutation2.setLinkPdb(TEST_LINK_PDB_2); - mutation2.setLinkMsa(TEST_LINK_MSA_2); mutation2.setNcbiBuild(TEST_NCBI_BUILD_2); mutation2.setVariantType(TEST_VARIANT_TYPE_2); - mutation2.setOncotatorRefseqMrnaId(TEST_ONCOTATOR_REFSEQ_MRNA_ID_2); - mutation2.setOncotatorProteinPosStart(TEST_ONCOTATOR_PROTEIN_POS_START_2); - mutation2.setOncotatorProteinPosEnd(TEST_ONCOTATOR_PROTEIN_POS_END_2); + mutation2.setRefseqMrnaId(TEST_MUTATION_REFSEQ_MRNA_ID_2); + mutation2.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_2); + mutation2.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_2); mutation2.setKeyword(TEST_KEYWORD_2); mutation2.setAnnotationJSON(NAME_SPACE_COLUMNS); mutationList.add(mutation2); diff --git a/web/src/test/java/org/cbioportal/web/StructuralVariantControllerTest.java b/web/src/test/java/org/cbioportal/web/StructuralVariantControllerTest.java index a8312d07817..3a8dcb8f3b1 100644 --- a/web/src/test/java/org/cbioportal/web/StructuralVariantControllerTest.java +++ b/web/src/test/java/org/cbioportal/web/StructuralVariantControllerTest.java @@ -58,7 +58,7 @@ @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@ContextConfiguration("/applicationContext-web.xml") +@ContextConfiguration("/applicationContext-web-test.xml") @Configuration public class StructuralVariantControllerTest { diff --git a/web/src/test/java/org/cbioportal/web/StudyViewControllerTest.java b/web/src/test/java/org/cbioportal/web/StudyViewControllerTest.java index 098107b2501..3951e57b963 100644 --- a/web/src/test/java/org/cbioportal/web/StudyViewControllerTest.java +++ b/web/src/test/java/org/cbioportal/web/StudyViewControllerTest.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.cbioportal.model.*; +import org.cbioportal.model.util.Select; import org.cbioportal.persistence.AlterationRepository; import org.cbioportal.service.*; import org.cbioportal.service.util.MolecularProfileUtil; @@ -61,6 +62,11 @@ public class StudyViewControllerTest { private static final String TEST_GENERIC_ASSAY_DATA_VALUE_2 = "value2"; private static final String TEST_CLINICAL_EVENT_TYPE = "STATUS"; private static final Integer TEST_CLINICAL_EVENT_TYPE_COUNT = 513; + private static final String TEST_CNA_ALTERATION_NAME_1 = "test_cna_event_type_1"; + private static final String TEST_CNA_ALTERATION_NAME_2 = "test_cna_event_type_2"; + private static final String TEST_CNA_ALTERATION_VALUE_1 = "2"; + private static final String TEST_CNA_ALTERATION_VALUE_2 = "-2"; + private static final String TEST_MOLECULAR_PROFILE_TYPE = "test_molecular_profile_type"; private List filteredSampleIdentifiers = new ArrayList<>(); private List clinicalData = new ArrayList<>(); @@ -128,6 +134,9 @@ public ViolinPlotService violinPlotService() { return mock(ViolinPlotService.class); } + + private ArrayList filteredSamples = new ArrayList<>(); + @Before public void setUp() throws Exception { @@ -136,6 +145,17 @@ public void setUp() throws Exception { sampleIdentifier.setStudyId(TEST_STUDY_ID); filteredSampleIdentifiers.add(sampleIdentifier); + Sample sample1 = new Sample(); + sample1.setStableId(TEST_SAMPLE_ID_1); + sample1.setPatientStableId(TEST_PATIENT_ID_1); + sample1.setCancerStudyIdentifier(TEST_STUDY_ID); + Sample sample2 = new Sample(); + sample2.setStableId(TEST_SAMPLE_ID_2); + sample2.setPatientStableId(TEST_PATIENT_ID_2); + sample2.setCancerStudyIdentifier(TEST_STUDY_ID); + filteredSamples.add(sample1); + filteredSamples.add(sample2); + ClinicalData clinicalData1 = new ClinicalData(); clinicalData1.setAttrId(TEST_ATTRIBUTE_ID); clinicalData1.setAttrValue(TEST_CLINICAL_DATA_VALUE_1); @@ -491,6 +511,92 @@ public void fetchSampleCounts() throws Exception { .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value(2)); } + + @Test + public void fetchGenomicDataCounts() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + List genomicDataCountItems = new ArrayList<>(); + + GenomicDataCount genomicDataCount1 = new GenomicDataCount(); + genomicDataCount1.setLabel(TEST_CNA_ALTERATION_NAME_1); + genomicDataCount1.setValue(TEST_CNA_ALTERATION_VALUE_1); + genomicDataCount1.setCount(1); + + GenomicDataCount genomicDataCount2 = new GenomicDataCount(); + genomicDataCount2.setLabel(TEST_CNA_ALTERATION_NAME_2); + genomicDataCount2.setValue(TEST_CNA_ALTERATION_VALUE_2); + genomicDataCount2.setCount(1); + + GenomicDataCountItem genomicDataCountItem1 = new GenomicDataCountItem(); + List genomicDataCounts1 = new ArrayList<>(); + genomicDataCounts1.add(genomicDataCount1); + genomicDataCounts1.add(genomicDataCount2); + genomicDataCountItem1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + genomicDataCountItem1.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataCountItem1.setCounts(genomicDataCounts1); + + GenomicDataCountItem genomicDataCountItem2 = new GenomicDataCountItem(); + List genomicDataCounts2 = new ArrayList<>(); + genomicDataCounts2.add(genomicDataCount1); + genomicDataCounts2.add(genomicDataCount2); + genomicDataCountItem2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + genomicDataCountItem2.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataCountItem2.setCounts(genomicDataCounts2); + + genomicDataCountItems.add(genomicDataCountItem1); + genomicDataCountItems.add(genomicDataCountItem2); + + when(studyViewService.getCNAAlterationCountsByGeneSpecific( + anyList(), + anyList(), + anyList())) + .thenReturn(genomicDataCountItems); + + GenomicDataCountFilter genomicDataCountFilter = new GenomicDataCountFilter(); + List genomicDataFilters = new ArrayList<>(); + + GenomicDataFilter genomicDataFilter1 = new GenomicDataFilter(); + genomicDataFilter1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + genomicDataFilter1.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataFilters.add(genomicDataFilter1); + + GenomicDataFilter genomicDataFilter2 = new GenomicDataFilter(); + genomicDataFilter2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + genomicDataFilter2.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataFilters.add(genomicDataFilter2); + + genomicDataCountFilter.setGenomicDataFilters(genomicDataFilters); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + genomicDataCountFilter.setStudyViewFilter(studyViewFilter); + + mockMvc.perform(MockMvcRequestBuilders.post("/genomic-data-counts/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(genomicDataCountFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].profileType").value(TEST_MOLECULAR_PROFILE_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].label").value(TEST_CNA_ALTERATION_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].value").value(TEST_CNA_ALTERATION_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].label").value(TEST_CNA_ALTERATION_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].value").value(TEST_CNA_ALTERATION_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].profileType").value(TEST_MOLECULAR_PROFILE_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].label").value(TEST_CNA_ALTERATION_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].value").value(TEST_CNA_ALTERATION_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].label").value(TEST_CNA_ALTERATION_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].value").value(TEST_CNA_ALTERATION_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].count").value(1)); + } + @Ignore("Skip StudyViewControllerTest.fetchClinicalDataDensityPlot due to assertion errors") @Test public void fetchClinicalDataDensityPlot() throws Exception { @@ -765,9 +871,8 @@ public void fetchGenericAssayDataCounts() throws Exception { @Test public void fetchClinicalDataClinicalTable() throws Exception { - // For this sake of this test the sample clinical data and patient clinical data are identical. - when(clinicalDataService.fetchSampleClinicalDataClinicalTable(anyList(), anyList(), + when(clinicalDataService.fetchSampleClinicalTable(anyList(), anyList(), anyInt(), anyInt(), anyString(), any(), anyString())).thenReturn(clinicalData); when(clinicalDataService.fetchClinicalData(anyList(), anyList(), any(), anyString(), anyString())).thenReturn(clinicalData); @@ -801,7 +906,7 @@ public void fetchClinicalDataClinicalTable() throws Exception { @Test public void fetchClinicalEventTypeCounts() throws Exception { - List testEventTypeCounts = List.of(new ClinicalEventTypeCount(TEST_CLINICAL_EVENT_TYPE, TEST_CLINICAL_EVENT_TYPE_COUNT)); + List testEventTypeCounts = Arrays.asList(new ClinicalEventTypeCount(TEST_CLINICAL_EVENT_TYPE, TEST_CLINICAL_EVENT_TYPE_COUNT)); when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); when(clinicalEventService.getClinicalEventTypeCounts(anyList(), anyList())) @@ -820,4 +925,154 @@ public void fetchClinicalEventTypeCounts() throws Exception .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value(TEST_CLINICAL_EVENT_TYPE_COUNT)); } + @Test + public void validateStructVarFilter() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(studyViewFilterApplier.apply(any(), eq(false))).thenReturn(filteredSampleIdentifiers); + + List filteredSamples = new ArrayList<>(); + Sample sample1 = new Sample(); + sample1.setStableId(TEST_SAMPLE_ID_1); + sample1.setPatientStableId(TEST_PATIENT_ID_1); + sample1.setCancerStudyIdentifier(TEST_STUDY_ID); + filteredSamples.add(sample1); + Sample sample2 = new Sample(); + sample2.setStableId(TEST_SAMPLE_ID_2); + sample2.setPatientStableId(TEST_PATIENT_ID_2); + sample2.setCancerStudyIdentifier(TEST_STUDY_ID); + filteredSamples.add(sample2); + + when(sampleService.fetchSamples(anyList(), anyList(), + anyString())).thenReturn(filteredSamples); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + final StructuralVariantFilterQuery structVarFilterQuery = new StructuralVariantFilterQuery("A", null, "B", null, + true, true, true, Select.all(), + true, true, true, true); + final StudyViewStructuralVariantFilter structuralVariantFilter = new StudyViewStructuralVariantFilter(); + structuralVariantFilter.setStructVarQueries(Arrays.asList(Arrays.asList(structVarFilterQuery))); + studyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); + + // Test case: + structVarFilterQuery.getGene1Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + structVarFilterQuery.getGene2Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + + mockMvc.perform(MockMvcRequestBuilders.post("/filtered-samples/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + @Test + public void validateStructVarFilterBothAnyGene() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(studyViewFilterApplier.apply(any(), eq(false))).thenReturn(filteredSampleIdentifiers); + when(sampleService.fetchSamples(anyList(), anyList(), anyString())).thenReturn(filteredSamples); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + final StructuralVariantFilterQuery structVarFilterQuery = new StructuralVariantFilterQuery("A", null, "B", null, + true, true, true, Select.all(), + true, true, true, true); + final StudyViewStructuralVariantFilter structuralVariantFilter = new StudyViewStructuralVariantFilter(); + structuralVariantFilter.setStructVarQueries(Arrays.asList(Arrays.asList(structVarFilterQuery))); + studyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); + + // Test case: + structVarFilterQuery.getGene1Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + structVarFilterQuery.getGene2Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + + mockMvc.perform(MockMvcRequestBuilders.post("/filtered-samples/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + @Test + public void validateStructVarFilterBothNoGene() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(studyViewFilterApplier.apply(any(), eq(false))).thenReturn(filteredSampleIdentifiers); + when(sampleService.fetchSamples(anyList(), anyList(), anyString())).thenReturn(filteredSamples); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + final StructuralVariantFilterQuery structVarFilterQuery = new StructuralVariantFilterQuery("A", null, "B", null, + true, true, true, Select.all(), + true, true, true, true); + final StudyViewStructuralVariantFilter structuralVariantFilter = new StudyViewStructuralVariantFilter(); + structuralVariantFilter.setStructVarQueries(Arrays.asList(Arrays.asList(structVarFilterQuery))); + studyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); + + // Test case: + structVarFilterQuery.getGene1Query().setSpecialValue(StructuralVariantSpecialValue.NO_GENE); + structVarFilterQuery.getGene2Query().setSpecialValue(StructuralVariantSpecialValue.NO_GENE); + + mockMvc.perform(MockMvcRequestBuilders.post("/filtered-samples/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + @Test + public void validateStructVarFilterBothNoGeneId() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(studyViewFilterApplier.apply(any(), eq(false))).thenReturn(filteredSampleIdentifiers); + when(sampleService.fetchSamples(anyList(), anyList(), anyString())).thenReturn(filteredSamples); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + // Test case: + final StructuralVariantFilterQuery structVarFilterQuery = new StructuralVariantFilterQuery(null, null, null, null, + true, true, true, Select.all(), + true, true, true, true); + + final StudyViewStructuralVariantFilter structuralVariantFilter = new StudyViewStructuralVariantFilter(); + structuralVariantFilter.setStructVarQueries(Arrays.asList(Arrays.asList(structVarFilterQuery))); + studyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); + + mockMvc.perform(MockMvcRequestBuilders.post("/filtered-samples/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + @Test + public void validateStructVarFilterBothGeneIdAndSpecialValueNull() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(studyViewFilterApplier.apply(any(), eq(false))).thenReturn(filteredSampleIdentifiers); + when(sampleService.fetchSamples(anyList(), anyList(), anyString())).thenReturn(filteredSamples); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + // Test case: + final StructuralVariantFilterQuery structVarFilterQuery = new StructuralVariantFilterQuery(null, null, "B", null, + true, true, true, Select.all(), + true, true, true, true); + structVarFilterQuery.getGene1Query().setSpecialValue(null); + + final StudyViewStructuralVariantFilter structuralVariantFilter = new StudyViewStructuralVariantFilter(); + structuralVariantFilter.setStructVarQueries(Arrays.asList(Arrays.asList(structVarFilterQuery))); + studyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); + + mockMvc.perform(MockMvcRequestBuilders.post("/filtered-samples/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + } diff --git a/web/src/test/java/org/cbioportal/web/util/ClinicalDataBinUtilTest.java b/web/src/test/java/org/cbioportal/web/util/ClinicalDataBinUtilTest.java index 6e1284bd73c..83383756a04 100644 --- a/web/src/test/java/org/cbioportal/web/util/ClinicalDataBinUtilTest.java +++ b/web/src/test/java/org/cbioportal/web/util/ClinicalDataBinUtilTest.java @@ -1,15 +1,24 @@ package org.cbioportal.web.util; +import com.fasterxml.jackson.core.TreeNode; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; import org.cbioportal.model.ClinicalAttribute; import org.cbioportal.model.ClinicalData; import org.cbioportal.model.ClinicalDataBin; import org.cbioportal.model.Patient; import org.cbioportal.service.ClinicalAttributeService; import org.cbioportal.service.PatientService; +import org.cbioportal.service.impl.CustomDataServiceImpl; import org.cbioportal.service.util.ClinicalAttributeUtil; +import org.cbioportal.service.util.CustomAttributeWithData; +import org.cbioportal.service.util.CustomDataSession; +import org.cbioportal.service.util.CustomDataValue; +import org.cbioportal.service.util.SessionServiceRequestHandler; import org.cbioportal.web.parameter.*; -import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -19,13 +28,19 @@ import org.mockito.MockitoAnnotations; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; +import org.springframework.util.ResourceUtils; +import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) @@ -44,6 +59,13 @@ public class ClinicalDataBinUtilTest { private ClinicalAttributeService clinicalAttributeService; @Mock private PatientService patientService; + @Mock + private SessionServiceRequestHandler sessionServiceRequestHandler; + @Spy + private ObjectMapper sessionServiceObjectMapper = new ObjectMapper(); + @Spy + @InjectMocks + private CustomDataServiceImpl customDataService; @Spy private StudyViewFilterUtil studyViewFilterUtil; @Spy @@ -61,11 +83,19 @@ public class ClinicalDataBinUtilTest { @Spy @InjectMocks private ScientificSmallDataBinner scientificSmallDataBinner; + + @Spy + @InjectMocks + private IdPopulator idPopulator; + @Spy @InjectMocks private LogScaleDataBinner logScaleDataBinner; @Spy private DataBinHelper dataBinHelper; + private final String testDataAttributeId = "test"; + private final ObjectMapper customDatasetMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); @Before public void setup() { @@ -84,71 +114,73 @@ public void testUnfilteredFetchClinicalDataBinCounts() { // assert data bin counts - Assert.assertEquals(33, dataBins.size()); + assertEquals(33, dataBins.size()); List mutationCountBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("MUTATION_COUNT")).collect(Collectors.toList()); - Assert.assertEquals(6, mutationCountBins.size()); - Assert.assertEquals(2, mutationCountBins.get(0).getCount().intValue()); - Assert.assertEquals(1, mutationCountBins.get(1).getCount().intValue()); - Assert.assertEquals(1, mutationCountBins.get(2).getCount().intValue()); - Assert.assertEquals(1, mutationCountBins.get(3).getCount().intValue()); - Assert.assertEquals(1, mutationCountBins.get(4).getCount().intValue()); - Assert.assertEquals(1, mutationCountBins.get(5).getCount().intValue()); + assertEquals(6, mutationCountBins.size()); + assertEquals(2, mutationCountBins.get(0).getCount().intValue()); + assertEquals(1, mutationCountBins.get(1).getCount().intValue()); + assertEquals(1, mutationCountBins.get(2).getCount().intValue()); + assertEquals(1, mutationCountBins.get(3).getCount().intValue()); + assertEquals(1, mutationCountBins.get(4).getCount().intValue()); + assertEquals(1, mutationCountBins.get(5).getCount().intValue()); List fractionGenomeAlteredBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("FRACTION_GENOME_ALTERED")).collect(Collectors.toList()); - Assert.assertEquals(7, fractionGenomeAlteredBins.size()); - Assert.assertEquals(1, fractionGenomeAlteredBins.get(0).getCount().intValue()); - Assert.assertEquals(1, fractionGenomeAlteredBins.get(1).getCount().intValue()); - Assert.assertEquals(1, fractionGenomeAlteredBins.get(2).getCount().intValue()); - Assert.assertEquals(1, fractionGenomeAlteredBins.get(3).getCount().intValue()); - Assert.assertEquals(1, fractionGenomeAlteredBins.get(4).getCount().intValue()); - Assert.assertEquals(1, fractionGenomeAlteredBins.get(5).getCount().intValue()); - Assert.assertEquals(1, fractionGenomeAlteredBins.get(6).getCount().intValue()); + assertEquals(7, fractionGenomeAlteredBins.size()); + assertEquals(1, fractionGenomeAlteredBins.get(0).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(1).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(2).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(3).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(4).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(5).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(6).getCount().intValue()); List ageAtSeqReportedYearsBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("AGE_AT_SEQ_REPORTED_YEARS")).collect(Collectors.toList()); - Assert.assertEquals(6, ageAtSeqReportedYearsBins.size()); - Assert.assertEquals(1, ageAtSeqReportedYearsBins.get(0).getCount().intValue()); - Assert.assertEquals(1, ageAtSeqReportedYearsBins.get(1).getCount().intValue()); - Assert.assertEquals(2, ageAtSeqReportedYearsBins.get(2).getCount().intValue()); - Assert.assertEquals(1, ageAtSeqReportedYearsBins.get(3).getCount().intValue()); - Assert.assertEquals(1, ageAtSeqReportedYearsBins.get(4).getCount().intValue()); - Assert.assertEquals(1, ageAtSeqReportedYearsBins.get(5).getCount().intValue()); + assertEquals(6, ageAtSeqReportedYearsBins.size()); + assertEquals(1, ageAtSeqReportedYearsBins.get(0).getCount().intValue()); + assertEquals(1, ageAtSeqReportedYearsBins.get(1).getCount().intValue()); + assertEquals(2, ageAtSeqReportedYearsBins.get(2).getCount().intValue()); + assertEquals(1, ageAtSeqReportedYearsBins.get(3).getCount().intValue()); + assertEquals(1, ageAtSeqReportedYearsBins.get(4).getCount().intValue()); + assertEquals(1, ageAtSeqReportedYearsBins.get(5).getCount().intValue()); List caAgeBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("CA_AGE")).collect(Collectors.toList()); - Assert.assertEquals(5, caAgeBins.size()); - Assert.assertEquals(1, caAgeBins.get(0).getCount().intValue()); - Assert.assertEquals(1, caAgeBins.get(1).getCount().intValue()); - Assert.assertEquals(1, caAgeBins.get(2).getCount().intValue()); - Assert.assertEquals(1, caAgeBins.get(3).getCount().intValue()); - Assert.assertEquals(1, caAgeBins.get(4).getCount().intValue()); + assertEquals(5, caAgeBins.size()); + assertEquals(1, caAgeBins.get(0).getCount().intValue()); + assertEquals(1, caAgeBins.get(1).getCount().intValue()); + assertEquals(1, caAgeBins.get(2).getCount().intValue()); + assertEquals(1, caAgeBins.get(3).getCount().intValue()); + assertEquals(1, caAgeBins.get(4).getCount().intValue()); List cptSeqBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("CPT_SEQ_DATE")).collect(Collectors.toList()); - Assert.assertEquals(3, cptSeqBins.size()); - Assert.assertEquals(1, cptSeqBins.get(0).getCount().intValue()); - Assert.assertEquals(3, cptSeqBins.get(1).getCount().intValue()); - Assert.assertEquals(3, cptSeqBins.get(2).getCount().intValue()); + assertEquals(3, cptSeqBins.size()); + assertEquals(1, cptSeqBins.get(0).getCount().intValue()); + assertEquals(3, cptSeqBins.get(1).getCount().intValue()); + assertEquals(3, cptSeqBins.get(2).getCount().intValue()); List cptOrderIntBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("CPT_ORDER_INT")).collect(Collectors.toList()); - Assert.assertEquals(1, cptOrderIntBins.size()); - Assert.assertEquals(7, cptOrderIntBins.get(0).getCount().intValue()); + assertEquals(1, cptOrderIntBins.size()); + assertEquals(7, cptOrderIntBins.get(0).getCount().intValue()); List hybridDeathIntBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("HYBRID_DEATH_INT")).collect(Collectors.toList()); - Assert.assertEquals(5, hybridDeathIntBins.size()); - Assert.assertEquals(1, hybridDeathIntBins.get(0).getCount().intValue()); - Assert.assertEquals(1, hybridDeathIntBins.get(1).getCount().intValue()); - Assert.assertEquals(1, hybridDeathIntBins.get(2).getCount().intValue()); - Assert.assertEquals(1, hybridDeathIntBins.get(3).getCount().intValue()); - Assert.assertEquals(1, hybridDeathIntBins.get(4).getCount().intValue()); + assertEquals(5, hybridDeathIntBins.size()); + assertEquals(1, hybridDeathIntBins.get(0).getCount().intValue()); + assertEquals(1, hybridDeathIntBins.get(1).getCount().intValue()); + assertEquals(1, hybridDeathIntBins.get(2).getCount().intValue()); + assertEquals(1, hybridDeathIntBins.get(3).getCount().intValue()); + assertEquals(1, hybridDeathIntBins.get(4).getCount().intValue()); // assert function calls + verify(idPopulator, times(1)) + .populateIdLists(any(), any()); // we don't expect filterClinicalData to be called for an unfiltered query verify(studyViewFilterUtil, never()) @@ -157,10 +189,6 @@ public void testUnfilteredFetchClinicalDataBinCounts() { // study view filter should be applied only once verify(studyViewFilterApplier, times(1)).apply(any()); - // ids should be populated only once - verify(clinicalDataBinUtil, times(1)) - .populateIdLists(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); - // should call the correct bin calculate method only once for the given binning method verify(clinicalDataBinUtil, times(1)) .calculateStaticDataBins(any(), any(), any(), any(), any(), any(), any(), any()); @@ -178,71 +206,70 @@ public void testFilteredFetchClinicalDataBinCounts() { mockQueryFilter() ); - // assert data bin counts - Assert.assertEquals(33, dataBins.size()); + assertEquals(33, dataBins.size()); List mutationCountBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("MUTATION_COUNT")).collect(Collectors.toList()); - Assert.assertEquals(6, mutationCountBins.size()); - Assert.assertEquals(0, mutationCountBins.get(0).getCount().intValue()); - Assert.assertEquals(0, mutationCountBins.get(1).getCount().intValue()); - Assert.assertEquals(0, mutationCountBins.get(2).getCount().intValue()); - Assert.assertEquals(1, mutationCountBins.get(3).getCount().intValue()); - Assert.assertEquals(1, mutationCountBins.get(4).getCount().intValue()); - Assert.assertEquals(0, mutationCountBins.get(5).getCount().intValue()); + assertEquals(6, mutationCountBins.size()); + assertEquals(0, mutationCountBins.get(0).getCount().intValue()); + assertEquals(0, mutationCountBins.get(1).getCount().intValue()); + assertEquals(0, mutationCountBins.get(2).getCount().intValue()); + assertEquals(1, mutationCountBins.get(3).getCount().intValue()); + assertEquals(1, mutationCountBins.get(4).getCount().intValue()); + assertEquals(0, mutationCountBins.get(5).getCount().intValue()); List fractionGenomeAlteredBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("FRACTION_GENOME_ALTERED")).collect(Collectors.toList()); - Assert.assertEquals(7, fractionGenomeAlteredBins.size()); - Assert.assertEquals(1, fractionGenomeAlteredBins.get(0).getCount().intValue()); - Assert.assertEquals(0, fractionGenomeAlteredBins.get(1).getCount().intValue()); - Assert.assertEquals(1, fractionGenomeAlteredBins.get(2).getCount().intValue()); - Assert.assertEquals(0, fractionGenomeAlteredBins.get(3).getCount().intValue()); - Assert.assertEquals(0, fractionGenomeAlteredBins.get(4).getCount().intValue()); - Assert.assertEquals(0, fractionGenomeAlteredBins.get(5).getCount().intValue()); - Assert.assertEquals(0, fractionGenomeAlteredBins.get(6).getCount().intValue()); + assertEquals(7, fractionGenomeAlteredBins.size()); + assertEquals(1, fractionGenomeAlteredBins.get(0).getCount().intValue()); + assertEquals(0, fractionGenomeAlteredBins.get(1).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(2).getCount().intValue()); + assertEquals(0, fractionGenomeAlteredBins.get(3).getCount().intValue()); + assertEquals(0, fractionGenomeAlteredBins.get(4).getCount().intValue()); + assertEquals(0, fractionGenomeAlteredBins.get(5).getCount().intValue()); + assertEquals(0, fractionGenomeAlteredBins.get(6).getCount().intValue()); List ageAtSeqReportedYearsBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("AGE_AT_SEQ_REPORTED_YEARS")).collect(Collectors.toList()); - Assert.assertEquals(6, ageAtSeqReportedYearsBins.size()); - Assert.assertEquals(1, ageAtSeqReportedYearsBins.get(0).getCount().intValue()); - Assert.assertEquals(1, ageAtSeqReportedYearsBins.get(1).getCount().intValue()); - Assert.assertEquals(0, ageAtSeqReportedYearsBins.get(2).getCount().intValue()); - Assert.assertEquals(0, ageAtSeqReportedYearsBins.get(3).getCount().intValue()); - Assert.assertEquals(0, ageAtSeqReportedYearsBins.get(4).getCount().intValue()); - Assert.assertEquals(0, ageAtSeqReportedYearsBins.get(5).getCount().intValue()); + assertEquals(6, ageAtSeqReportedYearsBins.size()); + assertEquals(1, ageAtSeqReportedYearsBins.get(0).getCount().intValue()); + assertEquals(1, ageAtSeqReportedYearsBins.get(1).getCount().intValue()); + assertEquals(0, ageAtSeqReportedYearsBins.get(2).getCount().intValue()); + assertEquals(0, ageAtSeqReportedYearsBins.get(3).getCount().intValue()); + assertEquals(0, ageAtSeqReportedYearsBins.get(4).getCount().intValue()); + assertEquals(0, ageAtSeqReportedYearsBins.get(5).getCount().intValue()); List caAgeBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("CA_AGE")).collect(Collectors.toList()); - Assert.assertEquals(5, caAgeBins.size()); - Assert.assertEquals(1, caAgeBins.get(0).getCount().intValue()); - Assert.assertEquals(1, caAgeBins.get(1).getCount().intValue()); - Assert.assertEquals(0, caAgeBins.get(2).getCount().intValue()); - Assert.assertEquals(0, caAgeBins.get(3).getCount().intValue()); - Assert.assertEquals(0, caAgeBins.get(4).getCount().intValue()); + assertEquals(5, caAgeBins.size()); + assertEquals(1, caAgeBins.get(0).getCount().intValue()); + assertEquals(1, caAgeBins.get(1).getCount().intValue()); + assertEquals(0, caAgeBins.get(2).getCount().intValue()); + assertEquals(0, caAgeBins.get(3).getCount().intValue()); + assertEquals(0, caAgeBins.get(4).getCount().intValue()); List cptSeqBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("CPT_SEQ_DATE")).collect(Collectors.toList()); - Assert.assertEquals(3, cptSeqBins.size()); - Assert.assertEquals(0, cptSeqBins.get(0).getCount().intValue()); - Assert.assertEquals(2, cptSeqBins.get(1).getCount().intValue()); - Assert.assertEquals(0, cptSeqBins.get(2).getCount().intValue()); + assertEquals(3, cptSeqBins.size()); + assertEquals(0, cptSeqBins.get(0).getCount().intValue()); + assertEquals(2, cptSeqBins.get(1).getCount().intValue()); + assertEquals(0, cptSeqBins.get(2).getCount().intValue()); List cptOrderIntBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("CPT_ORDER_INT")).collect(Collectors.toList()); - Assert.assertEquals(1, cptOrderIntBins.size()); - Assert.assertEquals(2, cptOrderIntBins.get(0).getCount().intValue()); + assertEquals(1, cptOrderIntBins.size()); + assertEquals(2, cptOrderIntBins.get(0).getCount().intValue()); List hybridDeathIntBins = dataBins.stream().filter(bin -> bin.getAttributeId().equals("HYBRID_DEATH_INT")).collect(Collectors.toList()); - Assert.assertEquals(5, hybridDeathIntBins.size()); - Assert.assertEquals(1, hybridDeathIntBins.get(0).getCount().intValue()); - Assert.assertEquals(0, hybridDeathIntBins.get(1).getCount().intValue()); - Assert.assertEquals(0, hybridDeathIntBins.get(2).getCount().intValue()); - Assert.assertEquals(1, hybridDeathIntBins.get(3).getCount().intValue()); - Assert.assertEquals(0, hybridDeathIntBins.get(4).getCount().intValue()); + assertEquals(5, hybridDeathIntBins.size()); + assertEquals(1, hybridDeathIntBins.get(0).getCount().intValue()); + assertEquals(0, hybridDeathIntBins.get(1).getCount().intValue()); + assertEquals(0, hybridDeathIntBins.get(2).getCount().intValue()); + assertEquals(1, hybridDeathIntBins.get(3).getCount().intValue()); + assertEquals(0, hybridDeathIntBins.get(4).getCount().intValue()); // assert function calls @@ -253,18 +280,120 @@ public void testFilteredFetchClinicalDataBinCounts() { // study view filter should be applied twice verify(studyViewFilterApplier, times(2)).apply(any()); - - // ids should be populated twice - verify(clinicalDataBinUtil, times(2)) - .populateIdLists(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); - + // should call the correct bin calculate method only once for the given binning method verify(clinicalDataBinUtil, times(1)) .calculateStaticDataBins(any(), any(), any(), any(), any(), any(), any(), any()); verify(clinicalDataBinUtil, never()) .calculateDynamicDataBins(any(), any(), any(), any(), any()); - } + } + @Test + public void fetchCustomDataBinCountsWithStaticBinningMethod() throws Exception { + String customDataset = getFileContents("classpath:custom-dataset.json"); + + mockCustomDataService(customDataset); + mockStudyViewFilterApplier(customDataset); + ClinicalDataBinCountFilter filter = createClinicalDataBinCountFilter(); + + List bins = clinicalDataBinUtil.fetchCustomDataBinCounts( + DataBinMethod.STATIC, + filter, + false + ); + + // Total number of bins: + assertEquals(11, bins.size()); + + // All bins should have the custom data set name as attribute: + List customDatasetAttributeBins = bins + .stream() + .filter(bin -> bin.getAttributeId().equals(testDataAttributeId)) + .collect(Collectors.toList()); + assertEquals(11, customDatasetAttributeBins.size()); + + assertEquals("<=", bins.get(0).getSpecialValue()); + assertEquals(3, bins.get(0).getCount().intValue()); + + // Bin size should be five: + assertEquals(5, bins.get(1).getEnd().intValue() - bins.get(1).getStart().intValue()); + assertEquals(5, bins.get(1).getCount().intValue()); + + assertEquals(8, bins.get(2).getCount().intValue()); + assertEquals(5, bins.get(3).getCount().intValue()); + assertEquals(8, bins.get(4).getCount().intValue()); + assertEquals(5, bins.get(5).getCount().intValue()); + assertEquals(8, bins.get(6).getCount().intValue()); + assertEquals(5, bins.get(7).getCount().intValue()); + assertEquals(6, bins.get(8).getCount().intValue()); + assertEquals(2, bins.get(9).getCount().intValue()); + + assertEquals(">", bins.get(10).getSpecialValue()); + assertEquals(1, bins.get(10).getCount().intValue()); + } + + @Test + public void fetchCustomDataBinCountsWithStaticBinningMethod_minimalExample() throws Exception { + String customDataset = getFileContents("classpath:custom-dataset-minimal.json"); + + mockCustomDataService(customDataset); + mockStudyViewFilterApplier(customDataset); + ClinicalDataBinCountFilter filter = createClinicalDataBinCountFilter(); + + List bins = clinicalDataBinUtil.fetchCustomDataBinCounts( + DataBinMethod.STATIC, + filter, + false + ); + + // Total number of bins: + assertEquals(13, bins.size()); + + // All bins should have the custom data set name as attribute: + List customDatasetAttributeBins = bins + .stream() + .filter(bin -> bin.getAttributeId().equals(testDataAttributeId)) + .collect(Collectors.toList()); + assertEquals(13, customDatasetAttributeBins.size()); + + // Start bin: + assertEquals("<=", bins.get(0).getSpecialValue()); + assertEquals(1, bins.get(0).getCount().intValue()); + assertEquals(-1.0, bins.get(0).getEnd().intValue(), 0); + + // Size of next bins should be 1: + assertEquals(1, bins.get(1).getEnd().intValue() - bins.get(1).getStart().intValue(), 0); + assertEquals(1, bins.get(1).getCount().intValue()); + + assertEquals(1, bins.get(2).getCount().intValue()); + assertEquals(2, bins.get(3).getCount().intValue()); + assertEquals(2, bins.get(4).getCount().intValue()); + assertEquals(1, bins.get(5).getCount().intValue()); + assertEquals(0, bins.get(6).getCount().intValue()); + assertEquals(1, bins.get(7).getCount().intValue()); + assertEquals(1, bins.get(8).getCount().intValue()); + assertEquals(1, bins.get(9).getCount().intValue()); + assertEquals(1, bins.get(10).getCount().intValue()); + assertEquals(1, bins.get(11).getCount().intValue()); + assertEquals(1, bins.get(12).getCount().intValue()); + + } + + private void mockStudyViewFilterApplier(String customDataset) throws IOException { + TreeNode path = customDatasetMapper.readTree(customDataset).path("data").path("data"); + + TypeReference> type = new TypeReference>() {}; + List customIDs = customDatasetMapper.readValue(customDatasetMapper.treeAsTokens(path), type); + + when( + studyViewFilterApplier.apply(any()) + ).thenReturn(customIDs); + } + + private String getFileContents(String resourceLocation) throws IOException { + return new String(Files.readAllBytes(ResourceUtils.getFile(resourceLocation).toPath())); + } + private void mockUnfilteredQuery() { mockMethods( @@ -306,7 +435,17 @@ private void mockFilteredQuery() mockFilteredClinicalAttributes() ); } - + + private static final String sessionTestKey = "testkey"; + + @Value("classpath:state.json") Resource stateFile; + + private void mockCustomDataService(String customDataset) throws Exception { + when( + sessionServiceRequestHandler.getSessionDataJson(any(), any()) + ).thenReturn(customDataset); + } + private void mockMethods( List sampleIdentifiers, List sampleIds, @@ -330,7 +469,6 @@ private void mockMethods( when( clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds(eq(studyIds), eq(attributeIds)) ).thenReturn(clinicalAttributes); - when( studyViewFilterApplier.apply(argThat(new StudyViewFilterMatcher(studyViewFilter))) ).thenReturn(sampleIdentifiers); @@ -348,7 +486,7 @@ private void mockMethods( clinicalDataFetcher.fetchClinicalDataForPatients(eq(studyIdsOfPatients), eq(patientIds), eq(patientAttributeIds)) ).thenReturn(clinicalDataForPatients); } - + private ClinicalDataBinCountFilter mockBaseFilter() { ClinicalDataBinCountFilter filter = new ClinicalDataBinCountFilter(); @@ -366,7 +504,7 @@ private ClinicalDataBinCountFilter mockQueryFilter() { return filter; } - + private List mockUnfilteredStudySampleUniqueKeys() { List keys = new ArrayList<>(); @@ -380,7 +518,7 @@ private List mockUnfilteredStudySampleUniqueKeys() { return keys; } - + private List mockFilteredStudySampleUniqueKeys() { List keys = new ArrayList<>(); @@ -389,7 +527,7 @@ private List mockFilteredStudySampleUniqueKeys() { return keys; } - + private List mockUnfilteredStudyPatientUniqueKeys() { List keys = new ArrayList<>(); @@ -401,7 +539,7 @@ private List mockUnfilteredStudyPatientUniqueKeys() { return keys; } - + private List mockFilteredStudyPatientUniqueKeys() { List keys = new ArrayList<>(); @@ -410,7 +548,7 @@ private List mockFilteredStudyPatientUniqueKeys() { return keys; } - + private List mockUnfilteredSampleIds() { List sampleIds = new ArrayList<>(); @@ -424,7 +562,7 @@ private List mockUnfilteredSampleIds() { return sampleIds; } - + private List mockFilteredSampleIds() { List sampleIds = new ArrayList<>(); @@ -445,7 +583,7 @@ private List mockUnfilteredPatientIds() { return patientIds; } - + private List mockFilteredPatientIds() { List patientIds = new ArrayList<>(); @@ -454,7 +592,7 @@ private List mockFilteredPatientIds() { return patientIds; } - + private List mockUnfilteredPatients() { return mockPatients(mockUnfilteredPatientIds()); } @@ -462,7 +600,7 @@ private List mockUnfilteredPatients() { private List mockFilteredPatients() { return mockPatients(mockFilteredPatientIds()); } - + private List mockPatients(List patientIds) { List patients = new ArrayList<>(); @@ -479,7 +617,7 @@ private List mockPatients(List patientIds) { private List mockUnfilteredStudyIds() { return Collections.nCopies(7, STUDY_ID); } - + private List mockFilteredStudyIds() { return Collections.nCopies(2, STUDY_ID); } @@ -487,11 +625,11 @@ private List mockFilteredStudyIds() { private List mockUnfilteredStudyIdsOfPatients() { return Collections.nCopies(5, STUDY_ID); } - + private List mockFilteredStudyIdsOfPatients() { return Collections.nCopies(2, STUDY_ID); } - + private List mockUnfilteredSampleIdentifiers() { return mockSampleIdentifiers(mockUnfilteredSampleIds()); } @@ -512,7 +650,7 @@ private List mockSampleIdentifiers(List sampleIds) { return sampleIdentifiers; } - + private List mockUnfilteredAttributeIds() { List attributeIds = new ArrayList<>(); @@ -542,7 +680,7 @@ private List mockUnfilteredPatientAttributeIds() { return attributeIds; } - + private List mockUnfilteredAttributes() { List attributes = new ArrayList<>(); List attributeIds = mockUnfilteredAttributeIds(); @@ -555,7 +693,7 @@ private List mockUnfilteredAttributes() { return attributes; } - + private ClinicalAttribute mockClinicalAttribute(String attrId, String displayName, boolean isPatientAttribute) { ClinicalAttribute attr = new ClinicalAttribute(); @@ -568,7 +706,7 @@ private ClinicalAttribute mockClinicalAttribute(String attrId, String displayNam return attr; } - + private List mockUnfilteredClinicalAttributes() { List clinicalAttributes = new ArrayList<>(); @@ -595,7 +733,7 @@ private List mockFilteredClinicalAttributes() { return clinicalAttributes; } - + private ClinicalData mockClinicalData(String id, String value, String patientId, String sampleId) { ClinicalData data = new ClinicalData(); @@ -608,7 +746,7 @@ private ClinicalData mockClinicalData(String id, String value, String patientId, return data; } - + private List mockUnfilteredClinicalDataForSamples() { List data = new ArrayList<>(); @@ -659,7 +797,7 @@ private List mockUnfilteredClinicalDataForPatients() { return data; } - + private StudyViewFilter mockUnfilteredStudyViewFilter() { StudyViewFilter studyViewFilter = new StudyViewFilter(); @@ -669,7 +807,7 @@ private StudyViewFilter mockUnfilteredStudyViewFilter() { return studyViewFilter; } - + private StudyViewFilter mockFilteredStudyViewFilter() { StudyViewFilter studyViewFilter = mockUnfilteredStudyViewFilter(); @@ -699,8 +837,8 @@ private StudyViewFilter mockFilteredStudyViewFilter() { } private class StudyViewFilterMatcher implements ArgumentMatcher { - private StudyViewFilter source; + private StudyViewFilter source; public StudyViewFilterMatcher(StudyViewFilter source) { this.source = source; } @@ -714,7 +852,7 @@ public boolean matches(StudyViewFilter target) { equalClinicalDataFilters(source.getClinicalDataFilters(), target.getClinicalDataFilters()) ); } - + private boolean equalClinicalDataFilters(List sourceFilters, List targetFilters) { if (sourceFilters == null && targetFilters == null) { return true; @@ -736,7 +874,7 @@ private boolean equalClinicalDataFilters(List sourceFilters, return true; } - + private boolean equalDataFilterValues(List sourceValues, List targetValues) { if (sourceValues == null && targetValues == null) { @@ -760,5 +898,22 @@ private boolean equalDataFilterValues(List sourceValues, List attributes = new ArrayList<>(); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(testDataAttributeId); + clinicalDataBinFilter.setBinMethod(DataBinFilter.BinMethod.CUSTOM); + StudyViewFilter studyViewFilter = new StudyViewFilter(); + ArrayList studyIds = new ArrayList<>(); + studyIds.add("study_es_0"); + studyViewFilter.setStudyIds(studyIds); + clinicalDataBinCountFilter.setStudyViewFilter(studyViewFilter); + attributes.add(clinicalDataBinFilter); + clinicalDataBinCountFilter.setAttributes(attributes); + return clinicalDataBinCountFilter; } } diff --git a/web/src/test/java/org/cbioportal/web/util/DataBinnerTest.java b/web/src/test/java/org/cbioportal/web/util/DataBinnerTest.java index 47f39a1a280..590ae85c8e6 100644 --- a/web/src/test/java/org/cbioportal/web/util/DataBinnerTest.java +++ b/web/src/test/java/org/cbioportal/web/util/DataBinnerTest.java @@ -4,6 +4,8 @@ import java.util.stream.IntStream; + +import org.cbioportal.model.Binnable; import org.cbioportal.model.ClinicalData; import org.cbioportal.model.DataBin; import org.cbioportal.web.parameter.BinsGeneratorConfig; @@ -57,7 +59,7 @@ public void setup() { MockitoAnnotations.initMocks(this); } - private List getCaseIds(List unfilteredClinicalData, boolean getPatientIds) { + private List getCaseIds(List unfilteredClinicalData, boolean getPatientIds) { return unfilteredClinicalData .stream() .map(datum -> studyViewFilterUtil.getCaseUniqueKey(datum.getStudyId(), @@ -73,7 +75,7 @@ public void testLinearDataBinner() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -136,7 +138,7 @@ public void testLinearDataBinnerWithRange() { clinicalDataBinFilter.setStart(new BigDecimal("39.5")); clinicalDataBinFilter.setEnd(new BigDecimal("80.5")); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -171,7 +173,7 @@ public void testLinearDataBinnerWithRangeOne() { clinicalDataBinFilter.setStart(new BigDecimal("39.5")); clinicalDataBinFilter.setEnd(new BigDecimal("80.5")); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -205,7 +207,7 @@ public void testLinearDataBinnerWithRangeTwo() { clinicalDataBinFilter.setStart(new BigDecimal("39.5")); clinicalDataBinFilter.setEnd(new BigDecimal("81.5")); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -245,7 +247,7 @@ public void testLinearDataBinnerWithRangeAndCustomBins() { clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); clinicalDataBinFilter.setCustomBins(Arrays.asList(50.0, 60.0, 70.0).stream().map(item -> BigDecimal.valueOf(item)).collect(Collectors.toList())); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -278,13 +280,13 @@ public void testStaticDataBinnerFilter() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List unfilteredClinicalData = mockClinicalData(attributeId, studyId, values); + List unfilteredClinicalData = mockClinicalData(attributeId, studyId, values); List unfilteredPatientIds = getCaseIds(unfilteredClinicalData, true); List unfilteredDataBins = dataBinner.calculateDataBins( clinicalDataBinFilter, ClinicalDataType.PATIENT, unfilteredClinicalData, unfilteredPatientIds); - List filteredClinicalData = unfilteredClinicalData.subList(0, 108); // (0, 60] interval + List filteredClinicalData = unfilteredClinicalData.subList(0, 108); // (0, 60] interval List filteredPatientIds = getCaseIds(filteredClinicalData, true); List filteredDataBins = dataBinner.calculateClinicalDataBins(clinicalDataBinFilter, @@ -365,7 +367,7 @@ public void testLinearDataBinnerWithNumberOfPetOrPetCtScans() { String attributeId = "N_SCANS_PET_CT_PT"; String[] values = mockData.get("genie_N_SCANS_PET_CT_PT"); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); @@ -395,7 +397,7 @@ public void testLinearDataBinnerWithNumberOfBoneScans() { String attributeId = "N_SCANS_BONE_PT"; String[] values = mockData.get("genie_N_SCANS_BONE_PT"); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); @@ -433,7 +435,7 @@ public void testLinearDataBinnerWithAgeAtWhichSequencingWasReported() { String attributeId = "AGE_AT_WHICH_SEQUENCING_WAS_REPORTED"; String[] values = mockData.get("genie_public_AGE_AT_WHICH_SEQUENCING_WAS_REPORTED"); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); @@ -530,7 +532,7 @@ public void testLinearDataBinnerWithPediatricAge() { clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); clinicalDataBinFilter.setCustomBins(Arrays.asList(18.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0).stream().map(item -> BigDecimal.valueOf(item)).collect(Collectors.toList())); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); @@ -591,7 +593,7 @@ public void testLinearDataBinnerWithPediatricAgeCustomBinsTest1() { clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); clinicalDataBinFilter.setCustomBins(Arrays.asList(18.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0).stream().map(item -> BigDecimal.valueOf(item)).collect(Collectors.toList())); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); @@ -626,7 +628,7 @@ public void testLinearDataBinnerWithPediatricAgeCustomBinsTest2() { clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); clinicalDataBinFilter.setCustomBins(Arrays.asList(18.0, 25.0, 30.0, 35.0).stream().map(item -> BigDecimal.valueOf(item)).collect(Collectors.toList())); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); @@ -658,7 +660,7 @@ public void testLinearDataBinnerWithPediatricAgeCustomBinsSingleBoundary() { clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); clinicalDataBinFilter.setCustomBins(Arrays.asList(30.0).stream().map(item -> BigDecimal.valueOf(item)).collect(Collectors.toList())); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); @@ -688,7 +690,7 @@ public void testLinearDataBinnerWithPediatricAgeCustomBinsTwoBoundaries() { clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); clinicalDataBinFilter.setCustomBins(Arrays.asList(20.0, 50.0).stream().map(item -> BigDecimal.valueOf(item)).collect(Collectors.toList())); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); @@ -722,7 +724,7 @@ public void testLinearDataBinnerWithPediatricAgeGenerateBins() { generateBins.setAnchorValue(new BigDecimal(50)); clinicalDataBinFilter.setBinsGeneratorConfig(generateBins); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); @@ -756,7 +758,7 @@ public void testLinearDataBinnerWithPediatricAgeMedianBins() { clinicalDataBinFilter.setAttributeId(attributeId); clinicalDataBinFilter.setBinMethod(BinMethod.MEDIAN); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); @@ -784,7 +786,7 @@ public void testLinearDataBinnerWithPediatricAgeQuartileBins() { clinicalDataBinFilter.setAttributeId(attributeId); clinicalDataBinFilter.setBinMethod(BinMethod.QUARTILE); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); @@ -811,7 +813,7 @@ public void testLinearDataBinnerQuartileBinsLowComplexitySeriesQ1Q2Q3Identical() clinicalDataBinFilter.setAttributeId(attributeId); clinicalDataBinFilter.setBinMethod(BinMethod.QUARTILE); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -833,7 +835,7 @@ public void testLinearDataBinnerQuartileBinsLowComplexitySeriesQ2Q3Identical() { clinicalDataBinFilter.setAttributeId(attributeId); clinicalDataBinFilter.setBinMethod(BinMethod.QUARTILE); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -854,7 +856,7 @@ public void testLinearDataBinnerWithBigNumbers() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -879,7 +881,7 @@ public void testLinearDataBinnerWithPredefinedAttribute() { clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); clinicalDataBinFilter.setCustomBins(Arrays.asList(1.0, 2.0, 5.0, 10.0, 30.0).stream().map(item -> BigDecimal.valueOf(item)).collect(Collectors.toList())); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List sampleIds = getCaseIds(clinicalData, false); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.SAMPLE, clinicalData, sampleIds); @@ -905,7 +907,7 @@ public void testLinearDataBinnerWithNA() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -939,7 +941,7 @@ public void testLinearDataBinnerWithZeroIQR() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List sampleIds = getCaseIds(clinicalData, false); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.SAMPLE, clinicalData, sampleIds); @@ -964,7 +966,7 @@ public void testLinearDataBinnerWithAlwaysZeroIQR() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List sampleIds = getCaseIds(clinicalData, false); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.SAMPLE, clinicalData, sampleIds, 5); @@ -985,7 +987,7 @@ public void testDiscreteDataBinner() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List sampleIds = getCaseIds(clinicalData, false); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.SAMPLE, clinicalData, sampleIds); @@ -1024,7 +1026,7 @@ public void testScientificDataBinner() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List sampleIds = getCaseIds(clinicalData, false); sampleIds.addAll(Arrays.asList(samplesWithNoClinicalData)); @@ -1060,7 +1062,7 @@ public void testLogScaleNoOutlierDataBinner() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List sampleIds = getCaseIds(clinicalData, false); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.SAMPLE, clinicalData, sampleIds); @@ -1108,7 +1110,7 @@ public void testLogScaleDataBinner() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -1153,7 +1155,7 @@ public void testLogScaleDisabledDataBinner() { clinicalDataBinFilter.setAttributeId(attributeId); clinicalDataBinFilter.setDisableLogScale(true); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -1181,7 +1183,7 @@ public void testNegativeLogScaleDataBinner() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -1205,7 +1207,7 @@ public void testLogScaleDataBinnerWithSpecialOutliers() { ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); clinicalDataBinFilter.setAttributeId(attributeId); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -1239,7 +1241,7 @@ public void testNegativeLogScaleDisabledDataBinner() { clinicalDataBinFilter.setAttributeId(attributeId); clinicalDataBinFilter.setDisableLogScale(true); - List clinicalData = mockClinicalData(attributeId, studyId, values); + List clinicalData = mockClinicalData(attributeId, studyId, values); List patientIds = getCaseIds(clinicalData, true); List dataBins = dataBinner.calculateDataBins(clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); @@ -1253,8 +1255,8 @@ public void testNegativeLogScaleDisabledDataBinner() { Assert.assertEquals(">", dataBins.get(13).getSpecialValue()); } - private List mockClinicalData(String attributeId, String studyId, String[] values) { - List clinicalDataList = new ArrayList<>(); + private List mockClinicalData(String attributeId, String studyId, String[] values) { + List clinicalDataList = new ArrayList<>(); for (int index = 0; index < values.length; index++) { diff --git a/web/src/test/java/org/cbioportal/web/util/StudyViewFilterApplierTest.java b/web/src/test/java/org/cbioportal/web/util/StudyViewFilterApplierTest.java index 82e4dd97c6f..ece4df04682 100644 --- a/web/src/test/java/org/cbioportal/web/util/StudyViewFilterApplierTest.java +++ b/web/src/test/java/org/cbioportal/web/util/StudyViewFilterApplierTest.java @@ -1,5 +1,6 @@ package org.cbioportal.web.util; +import com.fasterxml.jackson.databind.ObjectMapper; import org.cbioportal.model.*; import org.cbioportal.model.MolecularProfile.MolecularAlterationType; import org.cbioportal.model.util.Select; @@ -16,7 +17,9 @@ import org.cbioportal.service.SampleListService; import org.cbioportal.service.SampleService; import org.cbioportal.service.StructuralVariantService; +import org.cbioportal.service.impl.CustomDataServiceImpl; import org.cbioportal.service.util.MolecularProfileUtil; +import org.cbioportal.service.util.SessionServiceRequestHandler; import org.cbioportal.web.parameter.ClinicalDataFilter; import org.cbioportal.web.parameter.DataFilterValue; import org.cbioportal.web.parameter.GeneIdType; @@ -24,25 +27,27 @@ import org.cbioportal.web.parameter.Projection; import org.cbioportal.web.parameter.SampleIdentifier; import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.appliers.*; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.context.ApplicationContext; +import org.springframework.util.ResourceUtils; +import java.io.IOException; import java.math.BigDecimal; +import java.nio.file.Files; import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; +import static com.google.common.collect.ImmutableList.of; +import static com.google.common.collect.Lists.newArrayList; +import static java.util.stream.Collectors.*; import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.Silent.class) public class StudyViewFilterApplierTest { @@ -60,6 +65,7 @@ public class StudyViewFilterApplierTest { public static final String CLINICAL_ATTRIBUTE_ID_1 = "attribute_id1"; public static final String CLINICAL_ATTRIBUTE_ID_2 = "attribute_id2"; public static final String CLINICAL_ATTRIBUTE_ID_3 = "attribute_id3"; + public static final String CUSTOM_DATASET_ID = "custom_dataset_id"; public static final Integer ENTREZ_GENE_ID_1 = 1; public static final Integer ENTREZ_GENE_ID_2 = 2; public static final String HUGO_GENE_SYMBOL_1 = "HUGO_GENE_SYMBOL_1"; @@ -116,6 +122,19 @@ public class StudyViewFilterApplierTest { @InjectMocks private MolecularProfileUtil molecularProfileUtil; + @Mock + private SessionServiceRequestHandler sessionServiceRequestHandler; + @Spy + private ObjectMapper sessionServiceObjectMapper = new ObjectMapper(); + + @Spy + @InjectMocks + private CustomDataServiceImpl customDataService; + + @Spy + @InjectMocks + private CustomDataFilterApplier customDataFilterApplier; + @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -261,8 +280,8 @@ public void apply() throws Exception { patient4.setCancerStudyIdentifier(STUDY_ID); patients.add(patient4); - Mockito.when(sampleService.fetchSamples(studyIds, sampleIds, "ID")).thenReturn(samples); - Mockito.when(patientService.getPatientsOfSamples(studyIds, sampleIds)).thenReturn(patients); + when(sampleService.fetchSamples(studyIds, sampleIds, "ID")).thenReturn(samples); + when(patientService.getPatientsOfSamples(studyIds, sampleIds)).thenReturn(patients); List patientClinicalDataList = new ArrayList<>(); ClinicalData patientClinicalData1 = new ClinicalData(); @@ -287,7 +306,7 @@ public void apply() throws Exception { patientClinicalData3.setStudyId(STUDY_ID); patientClinicalDataList.add(patientClinicalData3); - Mockito.when(clinicalDataService.getPatientClinicalDataDetailedToSample( + when(clinicalDataService.getPatientClinicalDataDetailedToSample( Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), patientIds, Arrays.asList(CLINICAL_ATTRIBUTE_ID_1, CLINICAL_ATTRIBUTE_ID_2))).thenReturn(patientClinicalDataList); @@ -302,7 +321,7 @@ public void apply() throws Exception { updatedSamples.add(sample4); updatedSamples.add(sample5); - Mockito.when(sampleService.getSamplesOfPatientsInMultipleStudies(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), + when(sampleService.getSamplesOfPatientsInMultipleStudies(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), updatedPatientIds, "ID")).thenReturn(updatedSamples); List sampleClinicalDataList = new ArrayList<>(); @@ -343,7 +362,7 @@ public void apply() throws Exception { updatedSampleIds.add(SAMPLE_ID4); updatedSampleIds.add(SAMPLE_ID5); - Mockito.when( + when( clinicalDataService.fetchClinicalData(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3, SAMPLE_ID4, SAMPLE_ID5), Arrays.asList(CLINICAL_ATTRIBUTE_ID_1, CLINICAL_ATTRIBUTE_ID_2), "SAMPLE", "SUMMARY")) @@ -363,7 +382,7 @@ public void apply() throws Exception { updatedPatient3.setCancerStudyIdentifier(STUDY_ID); updatedPatients.add(updatedPatient3); - Mockito.when( + when( patientService.getPatientsOfSamples(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3, SAMPLE_ID4, SAMPLE_ID5))) .thenReturn(updatedPatients); @@ -379,7 +398,7 @@ public void apply() throws Exception { molecularProfile2.setMolecularAlterationType(MolecularAlterationType.COPY_NUMBER_ALTERATION); molecularProfile2.setDatatype("DISCRETE"); - Mockito.when(molecularProfileService.getMolecularProfilesInStudies(Arrays.asList(STUDY_ID), "SUMMARY")) + when(molecularProfileService.getMolecularProfilesInStudies(Arrays.asList(STUDY_ID), "SUMMARY")) .thenReturn(Arrays.asList(molecularProfile1, molecularProfile2)); List mutations = new ArrayList<>(); @@ -403,9 +422,9 @@ public void apply() throws Exception { Gene gene1 = new Gene(); gene1.setEntrezGeneId(ENTREZ_GENE_ID_1); gene1.setHugoGeneSymbol(HUGO_GENE_SYMBOL_1); - Mockito.when(geneService.fetchGenes(Arrays.asList(HUGO_GENE_SYMBOL_1), GeneIdType.HUGO_GENE_SYMBOL.name(), + when(geneService.fetchGenes(Arrays.asList(HUGO_GENE_SYMBOL_1), GeneIdType.HUGO_GENE_SYMBOL.name(), Projection.SUMMARY.name())).thenReturn(Arrays.asList(gene1)); - Mockito.when(mutationService.getMutationsInMultipleMolecularProfilesByGeneQueries( + when(mutationService.getMutationsInMultipleMolecularProfilesByGeneQueries( anyList(), anyList(), anyList(), anyString(), isNull(), isNull(), isNull(), isNull())).thenReturn(mutations); updatedSampleIds = new ArrayList<>(); @@ -427,7 +446,7 @@ public void apply() throws Exception { profileCaseIdentifier3.setMolecularProfileId(MOLECULAR_PROFILE_ID_2); molecularProfileCaseIdentifiers.add(profileCaseIdentifier3); - Mockito.when(molecularProfileService.getFirstDiscreteCNAProfileCaseIdentifiers(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), + when(molecularProfileService.getFirstDiscreteCNAProfileCaseIdentifiers(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), updatedSampleIds)) .thenReturn(molecularProfileCaseIdentifiers); @@ -448,10 +467,10 @@ public void apply() throws Exception { Gene gene2 = new Gene(); gene2.setEntrezGeneId(ENTREZ_GENE_ID_2); gene2.setHugoGeneSymbol(HUGO_GENE_SYMBOL_2); - Mockito.when(geneService.fetchGenes(Arrays.asList(HUGO_GENE_SYMBOL_2), GeneIdType.HUGO_GENE_SYMBOL.name(), + when(geneService.fetchGenes(Arrays.asList(HUGO_GENE_SYMBOL_2), GeneIdType.HUGO_GENE_SYMBOL.name(), Projection.SUMMARY.name())).thenReturn(Arrays.asList(gene2)); - Mockito.when(discreteCopyNumberService.getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + when(discreteCopyNumberService.getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( anyList(), anyList(), anyList(), anyString())).thenReturn(discreteCopyNumberDataList); List clinicalAttributeList = new ArrayList<>(); @@ -464,7 +483,7 @@ public void apply() throws Exception { clinicalAttribute2.setDatatype("STRING"); clinicalAttributeList.add(clinicalAttribute2); - Mockito.when(clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds(Arrays.asList(STUDY_ID), + when(clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds(Arrays.asList(STUDY_ID), Arrays.asList(CLINICAL_ATTRIBUTE_ID_1, CLINICAL_ATTRIBUTE_ID_2))).thenReturn(clinicalAttributeList); List result = studyViewFilterApplier.apply(studyViewFilter); @@ -555,8 +574,8 @@ public void applyIntervalFilters() throws Exception { patient4.setCancerStudyIdentifier(STUDY_ID); patients.add(patient4); - Mockito.when(sampleService.fetchSamples(studyIds, sampleIds, "ID")).thenReturn(samples); - Mockito.when(patientService.getPatientsOfSamples(studyIds, sampleIds)).thenReturn(patients); + when(sampleService.fetchSamples(studyIds, sampleIds, "ID")).thenReturn(samples); + when(patientService.getPatientsOfSamples(studyIds, sampleIds)).thenReturn(patients); List sampleClinicalDataList = new ArrayList<>(); ClinicalData sampleClinicalData1 = new ClinicalData(); @@ -590,12 +609,12 @@ public void applyIntervalFilters() throws Exception { sampleClinicalData5.setStudyId(STUDY_ID); sampleClinicalDataList.add(sampleClinicalData5); - Mockito.when( + when( clinicalDataService.fetchClinicalData(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), sampleIds, Arrays.asList(CLINICAL_ATTRIBUTE_ID_3), "SAMPLE", "SUMMARY")) .thenReturn(sampleClinicalDataList); - Mockito.when(clinicalDataService.getPatientClinicalDataDetailedToSample( + when(clinicalDataService.getPatientClinicalDataDetailedToSample( Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), sampleIds, Arrays.asList(CLINICAL_ATTRIBUTE_ID_3))).thenReturn(new ArrayList()); @@ -615,7 +634,7 @@ public void applyIntervalFilters() throws Exception { clinicalAttribute1.setDatatype("NUMBER"); clinicalAttributeList.add(clinicalAttribute1); - Mockito.when(clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds(Arrays.asList(STUDY_ID), + when(clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds(Arrays.asList(STUDY_ID), Arrays.asList(CLINICAL_ATTRIBUTE_ID_3))).thenReturn(clinicalAttributeList); List result1 = studyViewFilterApplier.apply(studyViewFilter); @@ -728,8 +747,8 @@ public void applyPatientLevelGenericAssayFilter() throws Exception { patient4.setCancerStudyIdentifier(STUDY_ID); patients.add(patient4); - Mockito.when(sampleService.fetchSamples(studyIds, sampleIds, "ID")).thenReturn(samples); - Mockito.when(patientService.getPatientsOfSamples(studyIds, sampleIds)).thenReturn(patients); + when(sampleService.fetchSamples(studyIds, sampleIds, "ID")).thenReturn(samples); + when(patientService.getPatientsOfSamples(studyIds, sampleIds)).thenReturn(patients); List molecularProfiles = new ArrayList<>(); MolecularProfile molecularProfile1 = new MolecularProfile(); @@ -738,7 +757,7 @@ public void applyPatientLevelGenericAssayFilter() throws Exception { molecularProfile1.setPatientLevel(true); molecularProfiles.add(molecularProfile1); - Mockito.when(molecularProfileService.getMolecularProfilesInStudies(Arrays.asList(STUDY_ID), "SUMMARY")).thenReturn(molecularProfiles); + when(molecularProfileService.getMolecularProfilesInStudies(Arrays.asList(STUDY_ID), "SUMMARY")).thenReturn(molecularProfiles); List genericAssayDataList = new ArrayList<>(); @@ -787,7 +806,7 @@ public void applyPatientLevelGenericAssayFilter() throws Exception { genericAssayData5.setValue("100"); genericAssayDataList.add(genericAssayData5); - Mockito.when(genericAssayService + when(genericAssayService .fetchGenericAssayData(Arrays.asList(MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_1), sampleIds, Arrays.asList(CLINICAL_ATTRIBUTE_ID_3), "SUMMARY")).thenReturn(genericAssayDataList); GenericAssayDataFilter genericAssayDataFilter = new GenericAssayDataFilter(); @@ -805,4 +824,122 @@ public void applyPatientLevelGenericAssayFilter() throws Exception { // And sample1 sample2 belong to patient1 Assert.assertEquals(4, result.size()); } + + @Test + public void applyNumericalCustomDataFilter() throws Exception { + // Create samples: + List sampleIdentifiers = new ArrayList<>(); + sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID1)); + sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID2)); + sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID3)); + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setSampleIdentifiers(sampleIdentifiers); + List sampleIds = sampleIdentifiers + .stream() + .map(SampleIdentifier::getSampleId) + .collect(toList()); + List studyIds = sampleIdentifiers + .stream() + .map(SampleIdentifier::getStudyId) + .collect(toList()); + List samples = sampleIdentifiers + .stream() + .map(si -> createSample(si.getSampleId())) + .collect(toList()); + + // Create custom dataset interval filter: sample value must be between 0 and 10 + ClinicalDataFilter customDataFilter = new ClinicalDataFilter(); + customDataFilter.setAttributeId(CUSTOM_DATASET_ID); + DataFilterValue intervalFilter = new DataFilterValue(); + intervalFilter.setStart(new BigDecimal("0")); + intervalFilter.setEnd(new BigDecimal("10")); + customDataFilter.setValues(of(intervalFilter)); + List customDataFilters = new ArrayList<>(); + customDataFilters.add(customDataFilter); + studyViewFilter.setCustomDataFilters(customDataFilters); + + // Mock sample service: + when(sampleService.fetchSamples(eq(studyIds), eq(sampleIds), eq("ID"))).thenReturn(samples); + + // Load custom dataset: + String customDataset = getFileContents("classpath:numerical-custom-dataset-filter-applier.json"); + mockCustomDataService(customDataset); + + List result = studyViewFilterApplier.apply(studyViewFilter); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void applyCategoricalCustomDataFilter() throws Exception { + // Create samples: + List sampleIdentifiers = new ArrayList<>(); + sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID1)); + sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID2)); + sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID3)); + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setSampleIdentifiers(sampleIdentifiers); + List sampleIds = sampleIdentifiers + .stream() + .map(SampleIdentifier::getSampleId) + .collect(toList()); + List studyIds = sampleIdentifiers + .stream() + .map(SampleIdentifier::getStudyId) + .collect(toList()); + List samples = sampleIdentifiers + .stream() + .map(si -> createSample(si.getSampleId())) + .collect(toList()); + + // Create custom dataset equality filter: sample value must be value2 + ClinicalDataFilter customDataFilter = new ClinicalDataFilter(); + customDataFilter.setAttributeId(CUSTOM_DATASET_ID); + customDataFilter.setValues(of(createDataFilterValue("value2"))); + List customDataFilters = new ArrayList<>(); + customDataFilters.add(customDataFilter); + studyViewFilter.setCustomDataFilters(customDataFilters); + + // Mock sample service: + when(sampleService.fetchSamples(eq(studyIds), eq(sampleIds), eq("ID"))).thenReturn(samples); + + // Load custom dataset: + String customDataset = getFileContents("classpath:categorical-custom-dataset-filter-applier.json"); + mockCustomDataService(customDataset); + + List result = studyViewFilterApplier.apply(studyViewFilter); + + Assert.assertEquals(1, result.size()); + } + + private DataFilterValue createDataFilterValue(String value) { + DataFilterValue equalityFilter = new DataFilterValue(); + equalityFilter.setValue(value); + return equalityFilter; + } + + private Sample createSample(String sampleId) { + Sample sample1 = new Sample(); + sample1.setStableId(sampleId); + sample1.setCancerStudyIdentifier(STUDY_ID); + return sample1; + } + + private SampleIdentifier createSampleIdentifier(String sampleId) { + SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); + sampleIdentifier1.setSampleId(sampleId); + sampleIdentifier1.setStudyId(STUDY_ID); + return sampleIdentifier1; + } + + private void mockCustomDataService(String customDatasetFile) throws Exception { + when( + sessionServiceRequestHandler.getSessionDataJson(any(), any()) + ).thenReturn(customDatasetFile); + } + + private String getFileContents(String resourceLocation) throws IOException { + return new String(Files.readAllBytes(ResourceUtils.getFile(resourceLocation).toPath())); + } + } diff --git a/web/src/test/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplierTest.java b/web/src/test/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplierTest.java new file mode 100644 index 00000000000..e8bd8efba6d --- /dev/null +++ b/web/src/test/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplierTest.java @@ -0,0 +1,142 @@ +package org.cbioportal.web.util.appliers; + +import org.cbioportal.model.MolecularProfile; +import org.cbioportal.model.StructuralVariantFilterQuery; +import org.cbioportal.model.StructuralVariant; +import org.cbioportal.model.StudyViewStructuralVariantFilter; +import org.cbioportal.model.util.Select; +import org.cbioportal.service.MolecularProfileService; +import org.cbioportal.service.impl.StructuralVariantServiceImpl; +import org.cbioportal.web.parameter.SampleIdentifier; +import org.cbioportal.web.parameter.StudyViewFilter; +import org.cbioportal.web.util.StudyViewFilterUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class StructuralVariantSubFilterApplierTest { + + static final String ST_1_ID = "ST_1_ID"; + static final String MP_1_ID = "MP_1_ID"; + static final String G1 = "G1"; + static final String G2 = "G2"; + + @InjectMocks + StructuralVariantSubFilterApplier subject; + + @Mock + MolecularProfileService molecularProfileService; + + @Mock + StructuralVariantServiceImpl structuralVariantService; + + @Mock + StudyViewFilterUtil studyViewFilterUtil; + + private StudyViewFilter emptyStudyViewFilter = new StudyViewFilter(); + private StudyViewFilter structVarStudyViewFilter = new StudyViewFilter(); + + @Before + public void setUp() throws Exception { + + // For the test this arrangement does not matter much. What is more important + // is the SVs returned by the structuralVariantService service mock in response to + // subsequent query filter calls. + List svA = Arrays.asList(createQuery(G1, G2)); + List svB = Arrays.asList(createQuery(G1, G2)); + List> svA_and_svB_filterQuery = Arrays.asList(svA, svB); + + final StudyViewStructuralVariantFilter structuralVariantFilter = new StudyViewStructuralVariantFilter(); + structuralVariantFilter.setStructVarQueries(svA_and_svB_filterQuery); + structuralVariantFilter.setMolecularProfileIds(new HashSet<>(Arrays.asList(MP_1_ID))); + structVarStudyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); + + MolecularProfile molecularProfile1 = new MolecularProfile(); + molecularProfile1.setStableId(MP_1_ID); + molecularProfile1.setCancerStudyIdentifier(ST_1_ID); + molecularProfile1.setMolecularAlterationType(MolecularProfile.MolecularAlterationType.STRUCTURAL_VARIANT); + + when(molecularProfileService.getMolecularProfilesInStudies(anyList(), eq("SUMMARY"))) + .thenReturn(Arrays.asList(molecularProfile1)); + + final List structuralVariantsQuerySvA = Arrays.asList( + createStructVar("1", ST_1_ID), + createStructVar("2", ST_1_ID), + createStructVar("3", ST_1_ID), + createStructVar("4", ST_1_ID), + createStructVar("5", ST_1_ID) + ); + // This result determines the final result. + final List structuralVariantsQuerySvB = Arrays.asList( + createStructVar("4", ST_1_ID), + createStructVar("5", ST_1_ID) + ); + // Subsequently, return results for svA and svB queries. + when(studyViewFilterUtil.resolveEntrezGeneIds(anyList())) + .thenReturn(svA, svB); + when(structuralVariantService.fetchStructuralVariantsByStructVarQueries(anyList(), anyList(), anyList()) + ).thenReturn(structuralVariantsQuerySvA, structuralVariantsQuerySvB); + } + + // Does the function return OR relations between genes in the sv query filter? + @Test + public void filter() { + List sampleIdentifiers = Arrays.asList( + createSampleId("1", ST_1_ID), + createSampleId("2", ST_1_ID), + createSampleId("3", ST_1_ID), + createSampleId("4", ST_1_ID), + createSampleId("5", ST_1_ID), + createSampleId("6", ST_1_ID), + createSampleId("7", ST_1_ID), + createSampleId("8", ST_1_ID), + createSampleId("9", ST_1_ID), + createSampleId("10", ST_1_ID) + ); + List expected = Arrays.asList( + createSampleId("4", ST_1_ID), + createSampleId("5", ST_1_ID) + ); + Assert.assertEquals(expected, subject.filter(sampleIdentifiers, structVarStudyViewFilter)); + } + + @Test + public void shouldApplyFilter() { + Assert.assertFalse(subject.shouldApplyFilter(emptyStudyViewFilter)); + Assert.assertTrue(subject.shouldApplyFilter(structVarStudyViewFilter)); + } + + private StructuralVariantFilterQuery createQuery(String gene1, String gene2) { + return new StructuralVariantFilterQuery(gene1, null, gene2, null, + true, true, true, Select.all(), + true, true, true, true); + } + + private SampleIdentifier createSampleId(String samplId, String studyId) { + final SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setStudyId(studyId); + sampleIdentifier.setSampleId(samplId); + return sampleIdentifier; + } + + private StructuralVariant createStructVar(String samplId, String studyId) { + final StructuralVariant structuralVariant = new StructuralVariant(); + structuralVariant.setStudyId(studyId); + structuralVariant.setSampleId(samplId); + return structuralVariant; + } + +} \ No newline at end of file diff --git a/web/src/test/resources/applicationContext-web-test.xml b/web/src/test/resources/applicationContext-web-test.xml index ccf22361969..7ddf28340cb 100644 --- a/web/src/test/resources/applicationContext-web-test.xml +++ b/web/src/test/resources/applicationContext-web-test.xml @@ -13,6 +13,10 @@ + + + + diff --git a/web/src/test/resources/categorical-custom-dataset-filter-applier.json b/web/src/test/resources/categorical-custom-dataset-filter-applier.json new file mode 100644 index 00000000000..6c2dbaad896 --- /dev/null +++ b/web/src/test/resources/categorical-custom-dataset-filter-applier.json @@ -0,0 +1,26 @@ +{ + "id": "custom_dataset_id", + "data": { + "owner": "custom_dataset_owner", + "origin": [ + "test" + ], + "created": 1674657017813, + "lastUpdated": 1674657017813, + "users": [ + "test" + ], + "displayName": "test", + "description": "test", + "datatype": "STRING", + "patientAttribute": false, + "priority": "0", + "data": [ + {"sampleId": "sample_id1", "patientId": "test_patient", "studyId": "study_id", "value": "value1"}, + {"sampleId": "sample_id2", "patientId": "test_patient", "studyId": "study_id", "value": "value2"}, + {"sampleId": "sample_id3", "patientId": "test_patient", "studyId": "study_id", "value": "value3"} + ] + }, + "source": "test", + "type": "custom_data" +} \ No newline at end of file diff --git a/web/src/test/resources/custom-dataset-minimal.json b/web/src/test/resources/custom-dataset-minimal.json new file mode 100644 index 00000000000..a4fce311aed --- /dev/null +++ b/web/src/test/resources/custom-dataset-minimal.json @@ -0,0 +1,48 @@ +{ + "id": "test", + "data": { + "owner": "test", + "origin": [ + "test" + ], + "created": 1674657017813, + "lastUpdated": 1674657017813, + "users": [ + "test" + ], + "displayName": "test", + "description": "test", + "datatype": "NUMBER", + "patientAttribute": false, + "priority": "0", + "data": [ + {"sampleId": "test-0-01", "patientId": "test-A", "studyId": "test", "value": "-1.1"}, + + {"sampleId": "test-0-01", "patientId": "test-A", "studyId": "test", "value": "0"}, + + {"sampleId": "test-1-same-patient-01", "patientId": "test-1-same-patient", "studyId": "test", "value": "1"}, + + {"sampleId": "test-1-same-patient-02", "patientId": "test-1-same-patient", "studyId": "test", "value": "1.1"}, + {"sampleId": "test-2-01", "patientId": "test-2", "studyId": "test", "value": "2"}, + + {"sampleId": "test-3-01", "patientId": "test-3", "studyId": "test", "value": "3"}, + {"sampleId": "test-other-patient-same-bin-01", "patientId": "test-other-patient-same-bin", "studyId": "test", "value": "3"}, + + {"sampleId": "test-5-01", "patientId": "test-5", "studyId": "test", "value": "4"}, + + {"sampleId": "test-6-01", "patientId": "test-6", "studyId": "test", "value": "6"}, + + {"sampleId": "test-7-01", "patientId": "test-7", "studyId": "test", "value": "7"}, + + {"sampleId": "test-8-01", "patientId": "test-8", "studyId": "test", "value": "8"}, + + {"sampleId": "test-9-01", "patientId": "test-9", "studyId": "test", "value": "9"}, + + {"sampleId": "test-9-01", "patientId": "test-9", "studyId": "test", "value": "10"}, + + {"sampleId": "test-9-01", "patientId": "test-9", "studyId": "test", "value": "11"} + ] + }, + "source": "test", + "type": "custom_data" +} \ No newline at end of file diff --git a/web/src/test/resources/custom-dataset.json b/web/src/test/resources/custom-dataset.json new file mode 100644 index 00000000000..d3cbf8a6a6b --- /dev/null +++ b/web/src/test/resources/custom-dataset.json @@ -0,0 +1,359 @@ +{ + "id": "test", + "data": { + "owner": "foo@bar.com", + "origin": [ + "none" + ], + "created": 1674657017813, + "lastUpdated": 1674657017813, + "users": [ + "foo@bar.com" + ], + "displayName": "Foo", + "description": "Bar", + "datatype": "NUMBER", + "patientAttribute": false, + "priority": "0", + "data": [ + { + "sampleId": "TCGA-A1-A0SB-01", + "patientId": "TCGA-A1-A0SB", + "studyId": "study_es_0", + "value": "23" + }, + { + "sampleId": "TCGA-A2-A04P-01", + "patientId": "TCGA-A2-A04P", + "studyId": "study_es_0", + "value": "1" + }, + { + "sampleId": "TCGA-A2-A0CV-01", + "patientId": "TCGA-A2-A0CV", + "studyId": "study_es_0", + "value": "5" + }, + { + "sampleId": "TCGA-A2-A0ET-01", + "patientId": "TCGA-A2-A0ET", + "studyId": "study_es_0", + "value": "7" + }, + { + "sampleId": "TCGA-A2-A0T4-01", + "patientId": "TCGA-A2-A0T4", + "studyId": "study_es_0", + "value": "7" + }, + { + "sampleId": "TCGA-A2-A1FV-01", + "patientId": "TCGA-A2-A1FV", + "studyId": "study_es_0", + "value": "6.7" + }, + { + "sampleId": "TCGA-A7-A0CE-01", + "patientId": "TCGA-A7-A0CE", + "studyId": "study_es_0", + "value": "5" + }, + { + "sampleId": "TCGA-A7-A26I-01", + "patientId": "TCGA-A7-A26I", + "studyId": "study_es_0", + "value": "9" + }, + { + "sampleId": "TCGA-A8-A07C-01", + "patientId": "TCGA-A8-A07C", + "studyId": "study_es_0", + "value": "11" + }, + { + "sampleId": "TCGA-A8-A083-01", + "patientId": "TCGA-A8-A083", + "studyId": "study_es_0", + "value": "11" + }, + { + "sampleId": "TCGA-A8-A08S-01", + "patientId": "TCGA-A8-A08S", + "studyId": "study_es_0", + "value": "10.7" + }, + { + "sampleId": "TCGA-A8-A09D-01", + "patientId": "TCGA-A8-A09D", + "studyId": "study_es_0", + "value": "9" + }, + { + "sampleId": "TCGA-A8-A0A4-01", + "patientId": "TCGA-A8-A0A4", + "studyId": "study_es_0", + "value": "13" + }, + { + "sampleId": "TCGA-AN-A0AL-01", + "patientId": "TCGA-AN-A0AL", + "studyId": "study_es_0", + "value": "15" + }, + { + "sampleId": "TCGA-AN-A0FY-01", + "patientId": "TCGA-AN-A0FY", + "studyId": "study_es_0", + "value": "15" + }, + { + "sampleId": "TCGA-AO-A03O-01", + "patientId": "TCGA-AO-A03O", + "studyId": "study_es_0", + "value": "14.7" + }, + { + "sampleId": "TCGA-AO-A0JC-01", + "patientId": "TCGA-AO-A0JC", + "studyId": "study_es_0", + "value": "13" + }, + { + "sampleId": "TCGA-AO-A12C-01", + "patientId": "TCGA-AO-A12C", + "studyId": "study_es_0", + "value": "17" + }, + { + "sampleId": "TCGA-AQ-A1H2-01", + "patientId": "TCGA-AQ-A1H2", + "studyId": "study_es_0", + "value": "19" + }, + { + "sampleId": "TCGA-AR-A0U3-01", + "patientId": "TCGA-AR-A0U3", + "studyId": "study_es_0", + "value": "19" + }, + { + "sampleId": "TCGA-AR-A1AW-01", + "patientId": "TCGA-AR-A1AW", + "studyId": "study_es_0", + "value": "18.7" + }, + { + "sampleId": "TCGA-AR-A24W-01", + "patientId": "TCGA-AR-A24W", + "studyId": "study_es_0", + "value": "17" + }, + { + "sampleId": "TCGA-B6-A0IC-01", + "patientId": "TCGA-B6-A0IC", + "studyId": "study_es_0", + "value": "21" + }, + { + "sampleId": "TCGA-B6-A0RM-01", + "patientId": "TCGA-B6-A0RM", + "studyId": "study_es_0", + "value": "23" + }, + { + "sampleId": "TCGA-B6-A0X0-01", + "patientId": "TCGA-B6-A0X0", + "studyId": "study_es_0", + "value": "23" + }, + { + "sampleId": "TCGA-BH-A0B2-01", + "patientId": "TCGA-BH-A0B2", + "studyId": "study_es_0", + "value": "22.7" + }, + { + "sampleId": "TCGA-BH-A0BP-01", + "patientId": "TCGA-BH-A0BP", + "studyId": "study_es_0", + "value": "21" + }, + { + "sampleId": "TCGA-BH-A0DI-01", + "patientId": "TCGA-BH-A0DI", + "studyId": "study_es_0", + "value": "25" + }, + { + "sampleId": "TCGA-BH-A0E9-01", + "patientId": "TCGA-BH-A0E9", + "studyId": "study_es_0", + "value": "27" + }, + { + "sampleId": "TCGA-BH-A0HI-01", + "patientId": "TCGA-BH-A0HI", + "studyId": "study_es_0", + "value": "27" + }, + { + "sampleId": "TCGA-BH-A0WA-01", + "patientId": "TCGA-BH-A0WA", + "studyId": "study_es_0", + "value": "26.7" + }, + { + "sampleId": "TCGA-BH-A18V-01", + "patientId": "TCGA-BH-A18V", + "studyId": "study_es_0", + "value": "25" + }, + { + "sampleId": "TCGA-BH-A1FC-01", + "patientId": "TCGA-BH-A1FC", + "studyId": "study_es_0", + "value": "29" + }, + { + "sampleId": "TCGA-BH-A209-01", + "patientId": "TCGA-BH-A209", + "studyId": "study_es_0", + "value": "31" + }, + { + "sampleId": "TCGA-C8-A130-01", + "patientId": "TCGA-C8-A130", + "studyId": "study_es_0", + "value": "31" + }, + { + "sampleId": "TCGA-C8-A1HN-01", + "patientId": "TCGA-C8-A1HN", + "studyId": "study_es_0", + "value": "30.7" + }, + { + "sampleId": "TCGA-D8-A141-01", + "patientId": "TCGA-D8-A141", + "studyId": "study_es_0", + "value": "29" + }, + { + "sampleId": "TCGA-D8-A1JI-01", + "patientId": "TCGA-D8-A1JI", + "studyId": "study_es_0", + "value": "33" + }, + { + "sampleId": "TCGA-D8-A1XB-01", + "patientId": "TCGA-D8-A1XB", + "studyId": "study_es_0", + "value": "35" + }, + { + "sampleId": "TCGA-D8-A1XW-01", + "patientId": "TCGA-D8-A1XW", + "studyId": "study_es_0", + "value": "35" + }, + { + "sampleId": "TCGA-D8-A27P-01", + "patientId": "TCGA-D8-A27P", + "studyId": "study_es_0", + "value": "34.7" + }, + { + "sampleId": "TCGA-E2-A14O-01", + "patientId": "TCGA-E2-A14O", + "studyId": "study_es_0", + "value": "33" + }, + { + "sampleId": "TCGA-E2-A156-01", + "patientId": "TCGA-E2-A156", + "studyId": "study_es_0", + "value": "37" + }, + { + "sampleId": "TCGA-E2-A15O-01", + "patientId": "TCGA-E2-A15O", + "studyId": "study_es_0", + "value": "39" + }, + { + "sampleId": "TCGA-E2-A1IH-01", + "patientId": "TCGA-E2-A1IH", + "studyId": "study_es_0", + "value": "39" + }, + { + "sampleId": "TCGA-E2-A1LH-01", + "patientId": "TCGA-E2-A1LH", + "studyId": "study_es_0", + "value": "38.7" + }, + { + "sampleId": "TCGA-E9-A1NG-01", + "patientId": "TCGA-E9-A1NG", + "studyId": "study_es_0", + "value": "37" + }, + { + "sampleId": "TCGA-E9-A1RF-01", + "patientId": "TCGA-E9-A1RF", + "studyId": "study_es_0", + "value": "41" + }, + { + "sampleId": "TCGA-E9-A245-01", + "patientId": "TCGA-E9-A245", + "studyId": "study_es_0", + "value": "43" + }, + { + "sampleId": "TCGA-EW-A1OW-01", + "patientId": "TCGA-EW-A1OW", + "studyId": "study_es_0", + "value": "43" + }, + { + "sampleId": "TCGA-EW-A1PF-01", + "patientId": "TCGA-EW-A1PF", + "studyId": "study_es_0", + "value": "42.7" + }, + { + "sampleId": "TCGA-GM-A2DL-01", + "patientId": "TCGA-GM-A2DL", + "studyId": "study_es_0", + "value": "41" + }, + { + "sampleId": "TEST_SAMPLE_14", + "patientId": "TEST_PATIENT_14", + "studyId": "study_es_0", + "value": "45" + }, + { + "sampleId": "TEST_SAMPLE_15", + "patientId": "TEST_PATIENT_15", + "studyId": "study_es_0", + "value": "46" + }, + { + "sampleId": "TEST_SAMPLE_2", + "patientId": "TEST_PATIENT_2", + "studyId": "study_es_0", + "value": "49" + }, + { + "sampleId": "TEST_SAMPLE_SOMATIC_HETEROZYGOUS", + "patientId": "TEST_PATIENT_NAMESPACE", + "studyId": "study_es_0", + "value": "54" + } + ] + }, + "source": "my_portal", + "type": "custom_data" +} \ No newline at end of file diff --git a/web/src/test/resources/numerical-custom-dataset-filter-applier.json b/web/src/test/resources/numerical-custom-dataset-filter-applier.json new file mode 100644 index 00000000000..f79461bf80a --- /dev/null +++ b/web/src/test/resources/numerical-custom-dataset-filter-applier.json @@ -0,0 +1,26 @@ +{ + "id": "custom_dataset_id", + "data": { + "owner": "custom_dataset_owner", + "origin": [ + "test" + ], + "created": 1674657017813, + "lastUpdated": 1674657017813, + "users": [ + "test" + ], + "displayName": "test", + "description": "test", + "datatype": "NUMBER", + "patientAttribute": false, + "priority": "0", + "data": [ + {"sampleId": "sample_id1", "patientId": "test_patient", "studyId": "study_id", "value": "-2"}, + {"sampleId": "sample_id2", "patientId": "test_patient", "studyId": "study_id", "value": "2"}, + {"sampleId": "sample_id3", "patientId": "test_patient", "studyId": "study_id", "value": "12"} + ] + }, + "source": "test", + "type": "custom_data" +} \ No newline at end of file