import _ from "lodash"; import { toast } from 'react-toastify'; import EditorActionsManager from "../managers/EditorActionsManager"; export default class CBioPortalAccessor{ static readonly CNA_GAIN = 2; static readonly GET_ALL_CANCER_STUDIES_URL = "https://www.cbioportal.org/webservice.do?cmd=getCancerStudies"; static readonly GET_GENETIC_PROFILES_URL = "https://www.cbioportal.org/webservice.do?cmd=getGeneticProfiles&cancer_study_id="; static readonly GET_PROFILE_DATA_URL = "https://www.cbioportal.org/webservice.do?cmd=getProfileData"; static readonly MRNA_EXP_STUDY_NAME = "_mrna_median_Zscores"; static readonly CNA_EXP_STUDY_NAME = "_gistic"; static readonly VALIDATE_GENES_URL = 'https://www.cbioportal.org/api/genes/fetch?geneIdType=HUGO_GENE_SYMBOL&projection=ID' static readonly MUTATION_EXP_STUDY_NAME = "_mutations"; static readonly CNA_DELETION = -2; static readonly Z_SCORE_UPPER_THRESHOLD = 2; static readonly Z_SCORE_LOWER_THRESHOLD = -2; static readonly MUTATION = "Mutation"; static readonly GENE_EXPRESSION = "Gene Expression"; static readonly CNA = "Copy Number Alteration"; getDataTypes(){ return [CBioPortalAccessor.MUTATION, CBioPortalAccessor.GENE_EXPRESSION, CBioPortalAccessor.CNA]; } /* * Retrieves all cancer studies from cBioPortal * **/ fetchCancerStudies(callbackFunction) { var cancerStudies = {}; var request = new XMLHttpRequest(); request.onreadystatechange = function () { if(request.readyState === XMLHttpRequest.DONE && request.status === 200) { // By lines // Match all new line character representations var seperator = /\r?\n|\r/; var lines = request.responseText.split(seperator); // start from first line skip node meta data for(var i = 1; i < lines.length; i++) { if (lines[i].length <= 0) continue; var lineData = lines[i].split('\t'); cancerStudies[lineData[0]] = lineData; } callbackFunction(cancerStudies); } else if (request.readyState === XMLHttpRequest.DONE && request.status !== 200) { toast.error("Could not retrieve studies!"); } }; request.open("GET", CBioPortalAccessor.GET_ALL_CANCER_STUDIES_URL); request.send(); }; /** * Retrieves all genetic profiles for given cancerStudy from cBioPortal */ getSupportedGeneticProfiles(cancerStudy, callbackFunction) { var outData = {}; var request = new XMLHttpRequest(); var self = this; request.onreadystatechange = function () { if(request.readyState === XMLHttpRequest.DONE && request.status === 200) { // By lines // Match all new line character representations var seperator = /\r?\n|\r/; var lines = request.responseText.split(seperator); // start from first line skip node meta data for(var i = 1; i < lines.length; i++) { if (lines[i].length <= 0) continue; var lineData = lines[i].split('\t'); var cancerProfileName = lineData[0]; if(self.isSupportedCancerProfile(cancerProfileName)) { outData[cancerProfileName] = lineData; } } callbackFunction(outData); } else if (request.readyState === XMLHttpRequest.DONE && request.status !== 200) { console.error("Error retrieving studies"); } }; request.open("GET", CBioPortalAccessor.GET_GENETIC_PROFILES_URL + cancerStudy); request.send(); }; isSupportedCancerProfile(cancerProfileName: string) { return (cancerProfileName.endsWith(CBioPortalAccessor.MRNA_EXP_STUDY_NAME) || cancerProfileName.endsWith(CBioPortalAccessor.CNA_EXP_STUDY_NAME) || cancerProfileName.endsWith(CBioPortalAccessor.MUTATION_EXP_STUDY_NAME)); }; static getDataType(cancerProfileName: string) { if ( cancerProfileName.endsWith(this.MRNA_EXP_STUDY_NAME)) { return this.GENE_EXPRESSION; } else if ( cancerProfileName.endsWith(this.CNA_EXP_STUDY_NAME)) { return this.CNA; } else if ( cancerProfileName.endsWith(this.MUTATION_EXP_STUDY_NAME)) { return this.MUTATION; } return ""; } calcAlterationPercentages(paramLines, geneticProfileId, callbackFunction) { // By lines // Match all new line character representations const seperator = /\r?\n|\r/; const lines = paramLines.split(seperator); let startIndex = 0; //Find starting index of actual data skip commented lines for (const i in lines) { if(!lines[i].startsWith('#')) { startIndex = parseInt(i); break; } } //Total number of tumor samples in the response const tumorSamples = lines[startIndex].split('\t'); const numOfTumorSamples = tumorSamples.length - 2; const outData: {} = {}; outData[geneticProfileId] = {}; const geneticProfileType = CBioPortalAccessor.getDataType(geneticProfileId); // skip meta line and iterate over tumor sample data for(let i = startIndex + 1; i < lines.length; i++) { if (lines[i].length <= 0) continue; //Iterate over samples for each gene to calculate profile data const lineData: string[] = lines[i].split('\t'); let profileDataAlteration = 0; for(let j = 2; j < lineData.length; j++) { if(lineData[j] !== 'NaN') { if( geneticProfileType === CBioPortalAccessor.MUTATION ) profileDataAlteration++; else if ( (geneticProfileType === CBioPortalAccessor.CNA) && ( parseInt(lineData[j]) === CBioPortalAccessor.CNA_GAIN || parseInt(lineData[j]) === CBioPortalAccessor.CNA_DELETION ) ){ profileDataAlteration++; } else if ( (geneticProfileType === CBioPortalAccessor.GENE_EXPRESSION) && (parseFloat(lineData[j]) >= CBioPortalAccessor.Z_SCORE_UPPER_THRESHOLD || parseFloat(lineData[j]) <= CBioPortalAccessor.Z_SCORE_LOWER_THRESHOLD)){ profileDataAlteration++; } } } // outData[geneticProfileId][lineData[1]] = ( profileDataAlteration / numOfTumorSamples ) * 100; } callbackFunction(outData); } /* * * Retrieves profile data associated with the parameters below from cBioPortal * @params { caseSetId: "gbm_tcga", geneticProfileId: "gbm_tcga_mutations", genes: ["BRCA1", "BRCA2", "TP53"] } * */ getProfileData(params, callbackFunction) { //params //caseSetId, geneticProfileId, genes const outData = {}; const request = new XMLHttpRequest(); const self = this; request.onreadystatechange = function () { if(request.readyState === XMLHttpRequest.DONE && request.status === 200) { self.calcAlterationPercentages(request.responseText, params.geneticProfileId, callbackFunction); toast.success(params.geneticProfileId + " has been succesfully loaded from cBioPortal."); } }; //Create query URL let queryURL = CBioPortalAccessor.GET_PROFILE_DATA_URL; //Fetch sequenced case list !! queryURL += "&case_set_id=" + params.caseSetId + "_sequenced"; queryURL += "&genetic_profile_id=" + params.geneticProfileId; queryURL += "&gene_list="; let isFirst = true; for(const gene of params.genes) { if(!isFirst){ queryURL += "+"; } else { isFirst = false; } queryURL += gene; } request.open("GET", queryURL); request.send(); }; validateGenes(nodeSymbols, editor: EditorActionsManager) { const request = new XMLHttpRequest(); const self = this; request.onreadystatechange = function () { if(request.readyState === XMLHttpRequest.DONE && request.status === 200) { const validGeneSymbols = JSON.parse(request.responseText); const validGeneArray = _.map(validGeneSymbols, function(object) { return object.hugoGeneSymbol; }); editor.highlightInvalidGenes(validGeneArray); } }; const queryURL = CBioPortalAccessor.VALIDATE_GENES_URL; request.open("POST", queryURL); request.setRequestHeader("Content-type", "application/json"); request.send(JSON.stringify(nodeSymbols)); } }