diff --git a/build/mutationMapper.css b/build/mutationMapper.css index 09cf0e8..379169a 100644 --- a/build/mutationMapper.css +++ b/build/mutationMapper.css @@ -110,10 +110,6 @@ font-weight: bold; color: #888888; } -.mutation-3d-tied { - color: #800080; - font-weight: bold; -} .mutation-3d-highlighted { color: #FFDD00; font-weight: bold; @@ -218,15 +214,19 @@ font-weight: bold; } .trunc_mutation { - color: #FF0000; + color: #000000; font-weight: bold; } .inframe_mutation { - color: #000000; + color: #8B4513; font-weight: bold; } .other_mutation { - color: #808080; + color: #8B00C9; + font-weight: bold; +} +.default_mutation { + color: #BB0000; font-weight: bold; } .uniform_mutation { @@ -548,6 +548,52 @@ padding-top: 5px; font-size: 90%; } +span.mutation-type-info { + padding-right: 10px; + display: inline-block; + line-height: 2.5em; +} + +.mutation-type-info-link { + cursor: pointer; +} + +div.mutation-info-panel-container { + padding-bottom: 10px; +} + +div.mutation-info-panel-content { + padding-left: 30px; +} + +span.mutation-type-count { + padding: 5px; + color: #EFEFEF; +} +span.missense_mutation_count { + background-color: #008000; + font-weight: bold; + border-radius: 10px; +} +span.trunc_mutation_count { + background-color: #000000; + font-weight: bold; + border-radius: 10px; +} +span.inframe_mutation_count { + background-color: #8B4513; + font-weight: bold; + border-radius: 10px; +} +span.other_mutation_count { + background-color: #8B00C9; + font-weight: bold; + border-radius: 10px; +} +span.mutation-type-label { + font-weight: normal; +} + /* * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. * @@ -648,6 +694,27 @@ padding-left:5px; padding-right:5px; } +.mutation-table-container .valid { + background: #CCFFCC; + color: #000000; + padding-left: 5px; + padding-right: 5px; + font-weight: bold; +} +.mutation-table-container .somatic { + background: #CCFFFF; + color: #000000; + padding-left: 5px; + padding-right: 5px; + font-weight: bold; +} +.mutation-table-container .germline { + background: #FFFFCC; + color: #000000; + padding-left: 3px; + padding-right: 3px; + font-weight: bold; +} .mutation-table-container .mutation-table-protein-change { font-weight: bold; font-style: italic; diff --git a/build/mutationMapper.js b/build/mutationMapper.js index 6cc104a..348679f 100644 --- a/build/mutationMapper.js +++ b/build/mutationMapper.js @@ -556,16 +556,116 @@ var MutationViewsUtil = (function() * Mapping between the mutation type (data) values and * view values. */ + + var _mutationStyleMap = { + missense: {label: "Missense", + longName: "Missense", + style: "missense_mutation", + mainType: "missense", + priority: 1}, + inframe: {label: "IF", + longName: "In-frame", + style: "inframe_mutation", + mainType: "inframe", + priority: 2}, + truncating: { + label: "Truncating", + longName: "Truncating", + style: "trunc_mutation", + mainType: "truncating", + priority: 4}, + nonsense: {label: "Nonsense", + longName: "Nonsense", + style: "trunc_mutation", + mainType: "truncating", + priority: 6}, + nonstop: {label: "Nonstop", + longName: "Nonstop", + style: "trunc_mutation", + mainType: "truncating", + priority: 7}, + nonstart: {label: "Nonstart", + longName: "Nonstart", + style: "trunc_mutation", + mainType: "truncating", + priority: 8}, + frameshift: {label: "FS", + longName: "Frame Shift", + style: "trunc_mutation", + mainType: "truncating", + priority: 4}, + frame_shift_del: {label: "FS del", + longName: "Frame Shift Deletion", + style: "trunc_mutation", + mainType: "truncating", + priority: 4}, + frame_shift_ins: {label: "FS ins", + longName: "Frame Shift Insertion", + style: "trunc_mutation", + mainType: "truncating", + priority: 5}, + in_frame_ins: {label: "IF ins", + longName: "In-frame Insertion", + style: "inframe_mutation", + mainType: "inframe", + priority: 3}, + in_frame_del: {label: "IF del", + longName: "In-frame Deletion", + style: "inframe_mutation", + mainType: "inframe", + priority: 2}, + splice_site: {label: "Splice", + longName: "Splice site", + style: "trunc_mutation", + mainType: "truncating", + priority: 9}, + fusion: {label: "Fusion", + longName: "Fusion", + style: "fusion", + mainType: "other", + priority: 10}, + other: {style: "other_mutation", + mainType: "other", + priority: 11} + }; + var _mutationTypeMap = { - missense_mutation: {label: "Missense", style: "missense_mutation"}, - nonsense_mutation: {label: "Nonsense", style: "trunc_mutation"}, - nonstop_mutation: {label: "Nonstop", style: "trunc_mutation"}, - frame_shift_del: {label: "FS del", style: "trunc_mutation"}, - frame_shift_ins: {label: "FS ins", style: "trunc_mutation"}, - in_frame_ins: {label: "IF ins", style: "inframe_mutation"}, - in_frame_del: {label: "IF del", style: "inframe_mutation"}, - splice_site: {label: "Splice", style: "trunc_mutation"}, - other: {style: "other_mutation"} + "missense_mutation": _mutationStyleMap.missense, + "missense": _mutationStyleMap.missense, + "missense_variant": _mutationStyleMap.missense, + "frame_shift_ins": _mutationStyleMap.frame_shift_ins, + "frame_shift_del": _mutationStyleMap.frame_shift_del, + "frameshift": _mutationStyleMap.frameshift, + "frameshift_deletion": _mutationStyleMap.frame_shift_del, + "frameshift_insertion": _mutationStyleMap.frame_shift_ins, + "de_novo_start_outofframe": _mutationStyleMap.frameshift, + "frameshift_variant": _mutationStyleMap.frameshift, + "nonsense_mutation": _mutationStyleMap.nonsense, + "nonsense": _mutationStyleMap.nonsense, + "stopgain_snv": _mutationStyleMap.nonsense, + "splice_site": _mutationStyleMap.splice_site, + "splice": _mutationStyleMap.splice_site, + "splice site": _mutationStyleMap.splice_site, + "splicing": _mutationStyleMap.splice_site, + "splice_site_snp": _mutationStyleMap.splice_site, + "splice_site_del": _mutationStyleMap.splice_site, + "splice_site_indel": _mutationStyleMap.splice_site, + "translation_start_site": _mutationStyleMap.nonstart, + "start_codon_snp": _mutationStyleMap.nonstart, + "start_codon_del": _mutationStyleMap.nonstart, + "nonstop_mutation": _mutationStyleMap.nonstop, + "in_frame_del": _mutationStyleMap.in_frame_del, + "in_frame_ins": _mutationStyleMap.in_frame_ins, + "indel": _mutationStyleMap.in_frame_del, + "nonframeshift_deletion": _mutationStyleMap.inframe, + "nonframeshift": _mutationStyleMap.inframe, + "nonframeshift insertion": _mutationStyleMap.inframe, + "nonframeshift_insertion": _mutationStyleMap.inframe, + "targeted_region": _mutationStyleMap.inframe, + "inframe": _mutationStyleMap.inframe, + "truncating": _mutationStyleMap.truncating, + "fusion": _mutationStyleMap.fusion, + "other": _mutationStyleMap.other }; /** @@ -626,10 +726,9 @@ var MutationViewsUtil = (function() * @param options {Object} view (mapper) options * @param tabs {String} tabs selector (main tabs containing mutations tab) * @param tabName {String} name of the target tab (actual mutations tab) - * @param mut3dVis {Object} 3D vis instance * @return {MutationMapper} a MutationMapper instance */ - function delayedInitMutationMapper(el, options, tabs, tabName, mut3dVis) + function delayedInitMutationMapper(el, options, tabs, tabName) { var mutationMapper = new MutationMapper(options); var initialized = false; @@ -637,7 +736,7 @@ var MutationViewsUtil = (function() // init view without a delay if the target container is already visible if ($(el).is(":visible")) { - mutationMapper.init(mut3dVis); + mutationMapper.init(); initialized = true; } @@ -649,7 +748,7 @@ var MutationViewsUtil = (function() // init only if it is not initialized yet if (!initialized) { - mutationMapper.init(mut3dVis); + mutationMapper.init(); initialized = true; } // if already init, then refresh genes tab @@ -691,8 +790,50 @@ var MutationViewsUtil = (function() }; } + /** + * Renders a placeholder image for data tables cell. + * + * @param imageLocation place holder image location (url) + * @returns {String} html string + */ + function renderTablePlaceholder(imageLocation) + { + imageLocation = imageLocation || "images/ajax-loader.gif"; + + // TODO customize width & height? + var vars = {loaderImage: imageLocation, width: 15, height: 15}; + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_placeholder_template"); + return templateFn(vars); + } + + /** + * Refreshes the entire column in the data table. + * This function does NOT update the actual value of the cells. + * The update is for re-rendering purposes only. + * + * @param dataTable + * @param indexMap + * @param columnName + */ + function refreshTableColumn(dataTable, indexMap, columnName) + { + var tableData = dataTable.fnGetData(); + + _.each(tableData, function(ele, i) { + dataTable.fnUpdate(null, i, indexMap[columnName], false, false); + }); + + if (tableData.length > 0) + { + // this update is required to re-render the entire column! + dataTable.fnUpdate(null, 0, indexMap[columnName]); + } + } + return { initMutationMapper: delayedInitMutationMapper, + renderTablePlaceHolder: renderTablePlaceholder, + refreshTableColumn: refreshTableColumn, defaultTableTooltipOpts: defaultTableTooltipOpts, getVisualStyleMaps: getVisualStyleMaps }; @@ -790,7 +931,8 @@ var MutationDetailsTableFormatter = (function() var tip = caseId; // display full case id as a tip // no need to bother with clipping the text for 1 or 2 chars. - if (caseId.length > maxLength + 2) + if (caseId != null && + caseId.length > maxLength + 2) { text = caseId.substring(0, maxLength) + "..."; style = "simple-tip"; // enable tooltip for long strings @@ -816,7 +958,11 @@ var MutationDetailsTableFormatter = (function() function _getMutationType(map, value) { var style, text; - value = value.toLowerCase(); + + if (value != null) + { + value = value.toLowerCase(); + } if (map[value] != null) { @@ -851,7 +997,11 @@ var MutationDetailsTableFormatter = (function() var style = "simple-tip"; var text = value; var tip = ""; - value = value.toLowerCase(); + + if (value != null) + { + value = value.toLowerCase(); + } if (map[value] != null) { @@ -880,7 +1030,11 @@ var MutationDetailsTableFormatter = (function() function _getValidationStatus(map, value) { var style, label, tip; - value = value.toLowerCase(); + + if (value != null) + { + value = value.toLowerCase(); + } if (map[value] != null) { @@ -920,7 +1074,11 @@ var MutationDetailsTableFormatter = (function() var fisClass = ""; var omaClass = ""; var value = ""; - fis = fis.toLowerCase(); + + if (fis != null) + { + fis = fis.toLowerCase(); + } if (map[fis] != null) { @@ -969,12 +1127,12 @@ var MutationDetailsTableFormatter = (function() function getPdbMatchLink(mutation) { - return getLink(mutation.pdbMatch); + return getLink(mutation.get("pdbMatch")); } function getIgvLink(mutation) { - return getLink(mutation.igvLink); + return getLink(mutation.get("igvLink")); } function getLink(value) @@ -1002,14 +1160,15 @@ var MutationDetailsTableFormatter = (function() // TODO additional tooltips are enabled (hardcoded) only for msk-impact study for now // this is cBioPortal specific implementation, we may want to make it generic in the future - if (mutation.aminoAcidChange != null && - mutation.aminoAcidChange.length > 0 && - mutation.aminoAcidChange != "NA" && - mutation.cancerStudyShort.toLowerCase().indexOf("msk-impact") != -1 && - isDifferentProteinChange(mutation.proteinChange, mutation.aminoAcidChange)) + if (mutation.get("aminoAcidChange") != null && + mutation.get("aminoAcidChange").length > 0 && + mutation.get("aminoAcidChange") !== "NA" && + mutation.get("cancerStudyShort") != null && + mutation.get("cancerStudyShort").toLowerCase().indexOf("msk-impact") != -1 && + isDifferentProteinChange(mutation.get("proteinChange"), mutation.get("aminoAcidChange"))) { additionalTip = "The original annotation file indicates a different value: " + - normalizeProteinChange(mutation.aminoAcidChange) + ""; + normalizeProteinChange(mutation.get("aminoAcidChange")) + ""; } // TODO disabled temporarily, enable when isoform support completely ready @@ -1024,7 +1183,7 @@ var MutationDetailsTableFormatter = (function() // "
Uniprot id: " + "" + mutation.uniprotId + ""; // } - return {text: normalizeProteinChange(mutation.proteinChange), + return {text: normalizeProteinChange(mutation.get("proteinChange")), style : style, tip: tip, additionalTip: additionalTip}; @@ -1106,7 +1265,7 @@ var MutationDetailsTableFormatter = (function() var style = "tumor_type"; var tip = ""; - return {text: mutation.tumorType, + return {text: mutation.get("tumorType"), style : style, tip: tip}; } @@ -1207,7 +1366,11 @@ var MutationDetailsTableFormatter = (function() // but sometimes we have no numerical score value var value; - text = text.toLowerCase(); + + if (text != null) + { + text = text.toLowerCase(); + } if (text == "low" || text == "l") { value = 2; @@ -1330,17 +1493,17 @@ var PileupUtil = (function() var mutationMap = {}; // process raw data to group mutations by types - for (var i=0; i < mutations.length; i++) - { - var type = mutations[i].mutationType.toLowerCase(); + _.each(mutations, function(mutation) { + var type = mutation.get("mutationType") || ""; + type = type.trim().toLowerCase(); if (mutationMap[type] == undefined) { mutationMap[type] = []; } - mutationMap[type].push(mutations[i]); - } + mutationMap[type].push(mutation); + }); return mutationMap; } @@ -1353,18 +1516,18 @@ var PileupUtil = (function() * @param pileup a pileup instance * @return {Array} array of mutation type and count pairs */ - function generateTypeArray(pileup) + function groupMutationsByType(pileup) { var map = generateTypeMap(pileup); var typeArray = []; // convert to array and sort by length (count) - for (var key in map) - { + _.each(_.keys(map), function(key) { typeArray.push({type: key, count: map[key].length}); - } + }); typeArray.sort(function(a, b) { + // TODO tie condition: priority? // descending sort return b.count - a.count; }); @@ -1380,7 +1543,7 @@ var PileupUtil = (function() * @param pileup a pileup instance * @return {Array} array of mutation type group and count pairs */ - function generateTypeGroupArray(pileup) + function groupMutationsByMainType(pileup) { var mutationTypeMap = MutationViewsUtil.getVisualStyleMaps().mutationType; @@ -1391,19 +1554,18 @@ var PileupUtil = (function() // group mutation types by using the type map // and count number of mutations in a group - for (var type in typeMap) - { + _.each(_.keys(typeMap), function(type) { // grouping mutations by the style (not by the type) var group = undefined; if (mutationTypeMap[type] != null) { - group = mutationTypeMap[type].style; + group = mutationTypeMap[type].mainType; } if (group == undefined) { - group = mutationTypeMap.other.style; + group = mutationTypeMap.other.mainType; } if (groupCountMap[group] == undefined) @@ -1412,19 +1574,26 @@ var PileupUtil = (function() groupCountMap[group] = 0; } - groupCountMap[group]++; - } + groupCountMap[group] += typeMap[type].length; + }); // convert to array and sort by length (count) - for (var group in groupCountMap) - { - groupArray.push({group: group, count: groupCountMap[group]}); - } + _.each(_.keys(groupCountMap), function(group) { + groupArray.push({type: group, + count: groupCountMap[group], + priority: mutationTypeMap[group].priority}); + }); groupArray.sort(function(a, b) { - // descending sort - return b.count - a.count; + if (b.count === a.count) { + // tie condition: use mutation type priority + return b.priority - a.priority; + } + else { + // descending sort + return b.count - a.count; + } }); return groupArray; @@ -1450,7 +1619,7 @@ var PileupUtil = (function() // map each mutation sid to its corresponding pileup _.each(pileups, function(pileup) { _.each(pileup.mutations, function(mutation) { - map[mutation.mutationSid] = pileup.pileupId; + map[mutation.get("mutationSid")] = pileup.pileupId; }) }); @@ -1476,7 +1645,8 @@ var PileupUtil = (function() var mutation = mutationColl.at(i); var location = mutation.getProteinStartPos(); - var type = mutation.mutationType.trim().toLowerCase(); + var type = mutation.get("mutationType") || ""; + type = type.trim().toLowerCase(); if (location != null && type != "fusion") { @@ -1492,8 +1662,7 @@ var PileupUtil = (function() // convert map into an array of piled mutation objects var pileupList = []; - for (var key in mutations) - { + _.each(_.keys(mutations), function(key) { var pileup = {}; pileup.pileupId = PileupUtil.nextId(); @@ -1503,15 +1672,15 @@ var PileupUtil = (function() pileup.label = generateLabel(mutations[key]); // The following calculates dist of mutations by cancer type pileup.stats = _.chain(mutations[key]) - .groupBy(function(mut) { return mut.cancerType; }) + .groupBy(function(mut) { return mut.get("cancerType"); }) .sortBy(function(stat) { return -stat.length; }) .reduce(function(seed, o) { - seed.push({ cancerType: o[0].cancerType, count: o.length }); + seed.push({ cancerType: o[0].get("cancerType"), count: o.length }); return seed; }, []).value(); pileupList.push(new Pileup(pileup)); - } + }); // sort (descending) the list wrt mutation count pileupList.sort(function(a, b) { @@ -1539,9 +1708,9 @@ var PileupUtil = (function() for (var i=0; i < mutationData.length; i++) { var aMutation = mutationData.at(i); - var exists = redMap[aMutation.mutationSid]; + var exists = redMap[aMutation.get("mutationSid")]; if(exists == null) { - redMap[aMutation.mutationSid] = true; + redMap[aMutation.get("mutationSid")] = true; } else { removeItems.push(aMutation); } @@ -1565,24 +1734,16 @@ var PileupUtil = (function() // create a set of protein change labels // (this is to eliminate duplicates) - for (var i = 0; i < mutations.length; i++) - { - if (mutations[i].proteinChange != null && - mutations[i].proteinChange.length > 0) + _.each(mutations, function(mutation) { + if (mutation.get("proteinChange") != null && + mutation.get("proteinChange").length > 0) { - mutationSet[mutations[i].proteinChange] = mutations[i].proteinChange; + mutationSet[mutation.get("proteinChange")] = mutation.get("proteinChange"); } - } + }); // convert to array & sort - var mutationArray = []; - - for (var key in mutationSet) - { - mutationArray.push(key); - } - - mutationArray.sort(); + var mutationArray = _.keys(mutationSet).sort(); // find longest common starting substring // (this is to truncate redundant starting substring) @@ -1602,10 +1763,9 @@ var PileupUtil = (function() // generate the string var label = startStr; - for (var i = 0; i < mutationArray.length; i++) - { - label += mutationArray[i].substring(startStr.length) + "/"; - } + _.each(mutationArray, function(mutation) { + label += mutation.substring(startStr.length) + "/"; + }); // remove the last slash return label.substring(0, label.length - 1); @@ -1628,14 +1788,33 @@ var PileupUtil = (function() return total; } + /** + * Returns all the mutation model instances within the given + * collection of pileups. + * + * @param pileups a collection of pileups + * @returns {Array} mutations within the given pileups + */ + function getPileupMutations(pileups) + { + var mutations = []; + + _.each(pileups, function(pileup) { + mutations = mutations.concat(pileup.get("mutations") || []); + }); + + return mutations; + } + return { nextId: nextId, mapToMutations: mapToMutations, convertToPileups: convertToPileups, countMutations: countMutations, + getPileupMutations: getPileupMutations, getMutationTypeMap: generateTypeMap, - getMutationTypeArray: generateTypeArray, - getMutationTypeGroups: generateTypeGroupArray + groupMutationsByType: groupMutationsByType, + groupMutationsByMainType: groupMutationsByMainType }; })(); /* @@ -1756,9 +1935,8 @@ var DataProxyUtil = (function() * Initializes data proxy instances for the given options. * * @param options data proxy options (for all proxies) - * @param mut3dVis [optional] 3D visualizer instance (only used to init pdb proxy) */ - function initDataProxies(options, mut3dVis) + function initDataProxies(options) { // init proxies var dataProxies = {}; @@ -1779,8 +1957,7 @@ var DataProxyUtil = (function() instance = initDataProxy(proxyOpts, function(proxyOpts) { var mutationProxy = dataProxies["mutationProxy"]; - if (mut3dVis != null && - mutationProxy != null && + if (mutationProxy != null && mutationProxy.hasData()) { proxyOpts.options.mutationUtil = mutationProxy.getMutationUtil(); @@ -2241,12 +2418,15 @@ function JmolScriptGenerator() return posStr; }; - var posStr = position.start.pdbPos + + var startPdbPos = position.start.pdbPos || position.start.pdbPosition; + var endPdbPos = position.end.pdbPos || position.end.pdbPosition; + + var posStr = startPdbPos + insertionStr(position.start.insertion); - if (position.end.pdbPos > position.start.pdbPos) + if (endPdbPos > startPdbPos) { - posStr += "-" + position.end.pdbPos + + posStr += "-" + endPdbPos + insertionStr(position.end.insertion); } @@ -2767,8 +2947,11 @@ function Mol3DScriptGenerator() function scriptPosition(position) { var residues = []; - var start = parseInt(position.start.pdbPos); - var end = parseInt(position.end.pdbPos); + var startPdbPos = position.start.pdbPos || position.start.pdbPosition; + var endPdbPos = position.end.pdbPos || position.end.pdbPosition; + + var start = parseInt(startPdbPos); + var end = parseInt(endPdbPos); for (var i=start; i <= end; i++) { @@ -3269,8 +3452,7 @@ function MolScriptGenerator() } // process mapped residues - for (var color in selection) - { + _.each(_.keys(selection), function(color) { // select positions (mutations) script.push(self.selectPositions(selection[color], chain.chainId)); @@ -3295,7 +3477,7 @@ function MolScriptGenerator() options.displaySideChain == "all", options, chain)); - } + }); if (options.restrictProtein) { @@ -3491,9 +3673,9 @@ var MutationDetailsUtil = function(mutations) { for(var i=0; i < mutations.length; i++) { - var position = {id: mutations[i].id, + var position = {id: mutations[i].get("mutationId"), start: mutations[i].getProteinStartPos(), - end: mutations[i].proteinPosEnd}; + end: mutations[i].get("proteinPosEnd")}; positions.push(position); } @@ -3537,14 +3719,19 @@ var MutationDetailsUtil = function(mutations) // process raw data to group mutations by genes for (var i=0; i < mutations.length; i++) { - var gene = mutations.at(i).geneSymbol.toUpperCase(); + var gene = mutations.at(i).get("geneSymbol"); - if (mutationMap[gene] == undefined) + if (gene != null) { - mutationMap[gene] = []; - } + gene = gene.toUpperCase(); + + if (mutationMap[gene] == undefined) + { + mutationMap[gene] = []; + } - mutationMap[gene].push(mutations.at(i)); + mutationMap[gene].push(mutations.at(i)); + } } return mutationMap; @@ -3565,14 +3752,19 @@ var MutationDetailsUtil = function(mutations) // process raw data to group mutations by genes for (var i=0; i < mutations.length; i++) { - var caseId = mutations.at(i).caseId.toLowerCase(); + var caseId = mutations.at(i).get("caseId"); - if (mutationMap[caseId] == undefined) + if (caseId != null) { - mutationMap[caseId] = []; - } + caseId = caseId.toLowerCase(); - mutationMap[caseId].push(mutations.at(i)); + if (mutationMap[caseId] == undefined) + { + mutationMap[caseId] = []; + } + + mutationMap[caseId].push(mutations.at(i)); + } } return mutationMap; @@ -3593,7 +3785,7 @@ var MutationDetailsUtil = function(mutations) // process raw data to group mutations by genes for (var i=0; i < mutations.length; i++) { - var mutationId = mutations.at(i).mutationId; + var mutationId = mutations.at(i).get("mutationId"); mutationMap[mutationId] = mutations.at(i); } @@ -3615,7 +3807,7 @@ var MutationDetailsUtil = function(mutations) // process raw data to group mutations by genes for (var i=0; i < mutations.length; i++) { - var keyword = mutations.at(i).keyword; + var keyword = mutations.at(i).get("keyword"); if (keyword != null) { @@ -3646,7 +3838,7 @@ var MutationDetailsUtil = function(mutations) // process raw data to group mutations by genes for (var i=0; i < mutations.length; i++) { - var proteinChange = mutations.at(i).proteinChange; + var proteinChange = mutations.at(i).get("proteinChange"); if (proteinChange != null) { @@ -3679,8 +3871,8 @@ var MutationDetailsUtil = function(mutations) { // using only protein position start is ambiguous, // so we also need gene symbol for the key... - var gene = mutations.at(i).geneSymbol; - var proteinPosStart = mutations.at(i).proteinPosStart; + var gene = mutations.at(i).get("geneSymbol"); + var proteinPosStart = mutations.at(i).get("proteinPosStart"); if (proteinPosStart != null && gene != null) { @@ -3709,10 +3901,17 @@ var MutationDetailsUtil = function(mutations) { var summary = "["; var rate; - + var germlineDenominator = mutationCount.numCases; + if (mutationCount.numGermline > 0) { - rate = (mutationCount.numGermline / mutationCount.numCases) * 100; + if (mutationCount.numGermlineCases !== undefined) + { + if (mutationCount.numGermlineCases > 0) { + germlineDenominator = mutationCount.numGermlineCases; + } + } + rate = (mutationCount.numGermline / germlineDenominator) * 100; summary += "Germline Mutation Rate: " + rate.toFixed(1) + "%, "; } @@ -3757,12 +3956,13 @@ var MutationDetailsUtil = function(mutations) for (var j=0; j < mutations.length; j++) { // skip mutations with different genes - if (mutations[j].geneSymbol.toLowerCase() != gene.toLowerCase()) + if (mutations[j].get("geneSymbol").toLowerCase() != gene.toLowerCase()) { continue; } - if (mutations[j].mutationStatus.toLowerCase() === GERMLINE) + if (mutations[j].get("mutationStatus") && + mutations[j].get("mutationStatus").toLowerCase() === GERMLINE) { // case has at least one germline mutation germline = 1; @@ -3805,7 +4005,7 @@ var MutationDetailsUtil = function(mutations) for (var i=0; i < mutations.length; i++) { - var cancerStudy = mutations[i].cancerStudy; + var cancerStudy = mutations[i].get("cancerStudy"); if(prevStudy == null) { prevStudy = cancerStudy; } else if(prevStudy != cancerStudy) { @@ -3849,8 +4049,8 @@ var MutationDetailsUtil = function(mutations) this.containsGermline = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.mutationStatus && - mutation.mutationStatus.toLowerCase() == GERMLINE); + return (mutation.get("mutationStatus") && + mutation.get("mutationStatus").toLowerCase() == GERMLINE); }); }; @@ -3862,8 +4062,8 @@ var MutationDetailsUtil = function(mutations) this.containsValidStatus = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.validationStatus && - mutation.validationStatus.toLowerCase() == VALID); + return (mutation.get("validationStatus") && + mutation.get("validationStatus").toLowerCase() == VALID); }); }; @@ -3875,8 +4075,8 @@ var MutationDetailsUtil = function(mutations) this.containsIgvLink = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.igvLink && - mutation.igvLink != "NA"); + return (mutation.get("igvLink") && + mutation.get("igvLink") != "NA"); }); }; @@ -3888,8 +4088,8 @@ var MutationDetailsUtil = function(mutations) this.containsAlleleFreqT = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.tumorFreq && - mutation.tumorFreq != "NA"); + return (mutation.get("tumorFreq") && + mutation.get("tumorFreq") != "NA"); }); }; @@ -3901,106 +4101,115 @@ var MutationDetailsUtil = function(mutations) this.containsCnaData = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.cna && - mutation.cna != "NA" && - mutation.cna != "unknown"); + return (mutation.get("cna") && + mutation.get("cna") != "NA" && + mutation.get("cna") != "unknown"); + }); + }; + + this.containsProteinChange = function(gene) + { + return this._contains(gene, function(mutation) { + return (mutation.get("proteinChange") && + mutation.get("proteinChange") != "NA" && + mutation.get("proteinChange") != "unknown"); }); }; this.containsCaseId = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.caseId && - mutation.caseId != "NA"); + return (mutation.get("caseId") && + mutation.get("caseId") != "NA"); }); }; this.containsChr = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.chr && - mutation.chr != "NA"); + return (mutation.get("chr") && + mutation.get("chr") != "NA"); }); }; this.containsStartPos = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.startPos && - mutation.startPos > 0); + return (mutation.get("startPos") && + mutation.get("startPos") > 0); }); }; this.containsRefAllele = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.referenceAllele && - mutation.referenceAllele != "NA"); + return (mutation.get("referenceAllele") && + mutation.get("referenceAllele") != "NA"); }); }; this.containsVarAllele = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.variantAllele && - mutation.variantAllele != "NA"); + return (mutation.get("variantAllele") && + mutation.get("variantAllele") != "NA"); }); }; this.containsEndPos = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.endPos && - mutation.endPos > 0); + return (mutation.get("endPos") && + mutation.get("endPos") > 0); }); }; this.containsFis = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.functionalImpactScore && - mutation.functionalImpactScore != "NA"); + return (mutation.get("functionalImpactScore") && + mutation.get("functionalImpactScore") != "NA"); }); }; this.containsCosmic = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.cosmic && - mutation.cosmicCount && - mutation.cosmicCount > 0); + return (mutation.get("cosmic") && + mutation.getCosmicCount() && + mutation.getCosmicCount() > 0); }); }; this.containsMutationType = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.mutationType && - mutation.mutationType != "NA"); + return (mutation.get("mutationType") && + mutation.get("mutationType") != "NA"); }); }; this.containsMutationCount = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.mutationCount && - mutation.mutationCount > 0); + return (mutation.get("mutationCount") && + mutation.get("mutationCount") > 0); }); }; this.containsKeyword = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.keyword && - mutation.keyword != "NA"); + return (mutation.get("keyword") && + mutation.get("keyword") != "NA"); }); }; this.containsMutationEventId = function(gene) { return this._contains(gene, function(mutation) { - return (mutation.mutationEventId && - mutation.mutationEventId != "NA"); + return (mutation.get("mutationEventId") && + mutation.get("mutationEventId") != "NA"); }); }; @@ -4021,9 +4230,9 @@ var MutationDetailsUtil = function(mutations) { for (var i=0; i < mutations.length; i++) { - if (mutations[i].tumorType) + if (mutations[i].get("tumorType")) { - tumorTypeMap[mutations[i].tumorType] = true; + tumorTypeMap[mutations[i].get("tumorType")] = true; } } } @@ -4051,7 +4260,7 @@ var MutationDetailsUtil = function(mutations) { for (var i=0; i < mutations.length; i++) { - var value = mutations[i][dataField]; + var value = mutations[i].get(dataField); if (value && !_.contains(excludeList, value)) @@ -4089,6 +4298,7 @@ var MutationDetailsUtil = function(mutations) this.processMutationData(mutations); } }; + /* * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. * @@ -4126,7 +4336,7 @@ var MutationDetailsUtil = function(mutations) */ function MutationInputParser () { - var _data = null; + var _data = null; // MutationCollection var _geneList = null; var _sampleList = null; var _idCounter = 0; @@ -4243,17 +4453,18 @@ function MutationInputParser () * Parses the entire input data and creates an array of mutation objects. * * @param input input string/file. - * @returns {Array} an array of mutation objects. + * @returns {MutationCollection} an array of mutation objects. */ function parseInput(input) { - var mutationData = []; + var mutationData = new MutationCollection(); var lines = input.split("\n"); if (lines.length > 0) { // assuming first line is a header + // TODO allow comments? var indexMap = buildIndexMap(lines[0]); // rest should be data @@ -4277,26 +4488,36 @@ function MutationInputParser () * * @param line single line of the input data * @param indexMap map of
pairs - * @returns {Object} a mutation object + * @returns {MutationModel} a mutation model object */ function parseLine(line, indexMap) { - // init mutation fields - var mutation = initMutation(); + //var mutation = initMutation(); + // init an empty mutation object + var mutation = new MutationModel(); // assuming values are separated by tabs var values = line.split("\t"); + var attributes = {}; // find the corresponding column for each field, and set the value - _.each(_.keys(mutation), function(key) { - mutation[key] = parseValue(key, values, indexMap); + _.each(_.keys(_headerMap), function(key) { + var value = parseValue(key, values, indexMap); + + if (value) + { + attributes[key] = value; + } }); - mutation.mutationId = mutation.mutationId || nextId(); + attributes.mutationId = attributes.mutationId || nextId(); // TODO mutationSid? - mutation.mutationSid = mutation.mutationSid || mutation.mutationId; + attributes.mutationSid = attributes.mutationSid || attributes.mutationId; + + attributes.variantKey = VariantAnnotationUtil.generateVariantKey(attributes); + mutation.set(attributes); return mutation; } @@ -4306,18 +4527,18 @@ function MutationInputParser () * @param field name of the mutation model field * @param values array of values for a single input line * @param indexMap map of
pairs - * @returns {string} data value for the given field name. + * @returns {string|undefined} data value for the given field name. */ function parseValue(field, values, indexMap) { // get the column name for the given field name var column = _headerMap[field]; var index = indexMap[column]; - var value = ""; + var value = undefined; if (index != null) { - value = values[index] || ""; + value = values[index] || undefined; } return value; @@ -4328,7 +4549,7 @@ function MutationInputParser () * instead of index constants. * * @param header header line (first line) of the input - * @returns map of
pairs + * @returns {object} map of
pairs */ function buildIndexMap(header) { @@ -4358,11 +4579,11 @@ function MutationInputParser () { var sampleSet = {}; - _.each(_data, function(mutation, idx) { - if (mutation.caseId != null && - mutation.caseId.length > 0) + _data.each(function(mutation, idx) { + if (mutation.get("caseId") != null && + mutation.get("caseId").length > 0) { - sampleSet[mutation.caseId] = mutation.caseId; + sampleSet[mutation.get("caseId")] = mutation.get("caseId"); } }); @@ -4383,12 +4604,12 @@ function MutationInputParser () { var geneSet = {}; - _.each(_data, function(mutation, idx) { - if (mutation.geneSymbol != null && - mutation.geneSymbol.length > 0) + _data.each(function(mutation, idx) { + if (mutation.get("geneSymbol") != null && + mutation.get("geneSymbol").length > 0) { - geneSet[mutation.geneSymbol.toUpperCase()] = - mutation.geneSymbol.toUpperCase(); + geneSet[mutation.get("geneSymbol").toUpperCase()] = + mutation.get("geneSymbol").toUpperCase(); } }); @@ -4549,6 +4770,27 @@ var PdbDataUtil = (function() */ function processPdbData(data) { + // ascending sort + // TODO do not sort if already sorted? + data.sort(function(a, b) { + var diff = a.uniprotFrom - b.uniprotFrom; + + // for consistency sort alphabetically if positions are same + if (diff === 0) + { + if (a.pdbId > b.pdbId) + { + diff = -1; + } + else + { + diff = 1; + } + } + + return diff; + }); + var alignmentModel = null; var pdbList = []; var pdbMap = {}; @@ -4570,28 +4812,64 @@ var PdbDataUtil = (function() }); // instantiate chain models - for (var pdbId in pdbMap) - { + _.each(_.keys(pdbMap), function(pdbId) { var chains = []; - for (var chain in pdbMap[pdbId]) - { + _.each(_.keys(pdbMap[pdbId]), function(chain) { var chainModel = new PdbChainModel({chainId: chain, alignments: pdbMap[pdbId][chain]}); chains.push(chainModel); - } + }); var pdbModel = new PdbModel({pdbId: pdbId, chains: chains}); pdbList.push(pdbModel); - } + }); // return new pdb model return new PdbCollection(pdbList); } + function alignmentString(attributes) + { + var sb = []; + + // process 3 alignment strings and create a visualization string + var midline = attributes.midlineAlign; + var uniprot = attributes.uniprotAlign; + var pdb = attributes.pdbAlign; + + if (midline.length === uniprot.length && + midline.length === pdb.length) + { + for (var i = 0; i < midline.length; i++) + { + // do not append anything if there is a gap in uniprot alignment + if (uniprot[i] !== '-') + { + if (pdb[i] === '-') + { + sb.push('-'); + } + else + { + sb.push(midline[i]); + } + } + } + } + else + { + // the execution should never reach here, + // if everything is OK with the data... + sb.push("NA"); + } + + return sb.join(""); + } + /** * Generates a pdb info summary for the given full pdb info object * and the chain id. @@ -4608,20 +4886,16 @@ var PdbDataUtil = (function() // TODO cache? // get chain specific molecule info - for (var key in pdbInfo.compound) - { - var mol = pdbInfo.compound[key]; - + _.find(pdbInfo.compound, function(mol) { if (mol.molecule && _.indexOf(mol.chain, chainId.toLowerCase()) != -1) { // chain is associated with this mol, // get the organism info from the source - summary.molecule = mol.molecule; - break; + return mol; } - } + }); return summary; } @@ -4639,10 +4913,7 @@ var PdbDataUtil = (function() var organism = "NA"; // TODO cache? - for (var key in pdbInfo.compound) - { - var mol = pdbInfo.compound[key]; - + _.find(pdbInfo.compound, function(mol) { if (_.indexOf(mol.chain, chainId.toLowerCase()) != -1 && pdbInfo.source[mol.mol_id] != null) { @@ -4650,10 +4921,9 @@ var PdbDataUtil = (function() // get the organism info from the source organism = pdbInfo.source[mol.mol_id].organism_scientific || organism; - - break; + return mol; } - } + }); return organism; } @@ -4778,11 +5048,12 @@ var PdbDataUtil = (function() var pdbMatch = null; var location = mutation.getProteinStartPos(); - var type = mutation.mutationType.trim().toLowerCase(); + var type = mutation.get("mutationType") || ""; + type = type.trim().toLowerCase(); // skip fusions or invalid locations if (location == null || - type == "fusion") + type === "fusion") { return pdbMatch; } @@ -4827,6 +5098,38 @@ var PdbDataUtil = (function() return pdbMatch; } + /** + * Processes mutation data to add pdb match data + * + * @param mutationData array of MutationModel instances + * @param pdbRowData pdb row data for the corresponding uniprot id + * @return {Array} mutation data array with additional attrs + */ + function addPdbMatchData(mutationData, pdbRowData) + { + if (!pdbRowData) + { + return mutationData; + } + + //var map = mutationUtil.getMutationIdMap(); + + _.each(mutationData, function(mutation, idx) { + if (mutation == null) + { + console.log('warning [processMutationData]: mutation (at index %d) is null.', idx); + return; + } + + // find the matching pdb + var match = PdbDataUtil.mutationToPdb(mutation, pdbRowData); + // update the raw mutation object + mutation.set({pdbMatch: match}); + }); + + return mutationData; + } + /** * Checks for a match for the specified location on the * given merged alignment. @@ -5186,8 +5489,10 @@ var PdbDataUtil = (function() ALIGNMENT_MINUS: ALIGNMENT_MINUS, ALIGNMENT_SPACE: ALIGNMENT_SPACE, // public functions + alignmentString: alignmentString, processPdbData: processPdbData, mutationToPdb: mutationToPdb, + addPdbMatchData: addPdbMatchData, allocateChainRows: allocateChainRows, mergeAlignments: mergeAlignments, generatePdbInfoSummary: generatePdbInfoSummary, @@ -5363,7 +5668,7 @@ PymolScriptGenerator.prototype.constructor = PymolScriptGenerator; /* - * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS @@ -5393,84 +5698,867 @@ PymolScriptGenerator.prototype.constructor = PymolScriptGenerator; */ /** - * Mutation Model. - * - * Current model is sufficient to visualize both the table and the diagram. - * Later we may add more data if necessary. + * A simple queue implementation for serializing requests. * * @author Selcuk Onur Sumer */ -var MutationModel = Backbone.Model.extend({ - initialize: function(attributes) { - this.mutationId = attributes.mutationId; - this.mutationSid = attributes.mutationSid; - this.geneticProfileId = attributes.geneticProfileId; - this.mutationEventId = attributes.mutationEventId; - this.caseId = attributes.caseId; - this.geneSymbol = attributes.geneSymbol; - this.linkToPatientView = attributes.linkToPatientView; - this.cancerType = attributes.cancerType; - this.cancerStudy = attributes.cancerStudy; - this.cancerStudyShort = attributes.cancerStudyShort; - this.cancerStudyLink = attributes.cancerStudyLink; - this.tumorType = attributes.tumorType; - this.proteinChange = attributes.proteinChange; - this.aminoAcidChange = attributes.aminoAcidChange; - this.mutationType = attributes.mutationType; - this.cosmic = attributes.cosmic; - this.cosmicCount = this.calcCosmicCount(attributes.cosmic); - this.functionalImpactScore = attributes.functionalImpactScore; - this.fisValue = attributes.fisValue; - this.msaLink = attributes.msaLink; - this.xVarLink = attributes.xVarLink; - this.pdbLink = attributes.pdbLink; - this.pdbMatch = attributes.pdbMatch; // {pdbId, chainId} pair - this.igvLink = attributes.igvLink; - this.mutationStatus = attributes.mutationStatus; - this.validationStatus = attributes.validationStatus; - this.sequencingCenter = attributes.sequencingCenter; - this.ncbiBuildNo = attributes.ncbiBuildNo; - this.chr = attributes.chr; - this.startPos = attributes.startPos; - this.endPos = attributes.endPos; - this.referenceAllele = attributes.referenceAllele; - this.variantAllele = attributes.variantAllele; - this.tumorFreq = attributes.tumorFreq; - this.normalFreq = attributes.normalFreq; - this.tumorRefCount = attributes.tumorRefCount; - this.tumorAltCount = attributes.tumorAltCount; - this.normalRefCount = attributes.normalRefCount; - this.normalAltCount = attributes.normalAltCount; - this.canonicalTranscript = attributes.canonicalTranscript; - this.refseqMrnaId = attributes.refseqMrnaId; - this.codonChange = attributes.codonChange; - this.uniprotId = attributes.uniprotId; - this.uniprotAcc = attributes.uniprotAcc; - this.proteinPosStart = attributes.proteinPosStart; - this.proteinPosEnd = attributes.proteinPosEnd; - this.mutationCount = attributes.mutationCount; - this.specialGeneData = attributes.specialGeneData; - this.keyword = attributes.keyword; - this.cna = attributes.cna; - this.myCancerGenome = attributes.myCancerGenome; - this.isHotspot = attributes.isHotspot; - }, - url: function() { - // TODO implement this to get the data from a web service - var urlStr = "webservice.do?cmd=..."; - }, - /** - * Finds out the protein start position for this mutation. - * The field proteinPosStart has a priority over proteinChange. - * If none of these has a valid value, then this function - * returns null. - * - * @return protein start position - */ - getProteinStartPos: function() +function RequestQueue(options) +{ + var self = this; + + var _defaultOpts = { + completeEvent: "requestQueueProcessComplete", + newRequestEvent: "requestQueueNewRequest" + }; + + var _options = jQuery.extend(true, {}, _defaultOpts, options); + + var _queryQueue = []; + var _queryInProgress = false; + var _dispatcher = {}; + _.extend(_dispatcher, Backbone.Events); + + /** + * Initializes the queue with the provided process function. + * + * @param processFn function to be invoked to process queue elements + */ + function init(processFn) + { + _dispatcher.on(_options.newRequestEvent, function() { + // no query in progress, ready to consume + if (!_queryInProgress) + { + processQueue(processFn); + } + }); + + _dispatcher.on(_options.completeEvent, function() { + processQueue(processFn); + }); + } + + // TODO find an efficient way to avoid hitting the server more than once + // for the exact same simultaneous query + + /** + * Processes the queue by invoking the given process function + * for the current element in the queue. + * + * @param processFn function to process the queue element + */ + function processQueue(processFn) + { + // get the first element from the queue + var element = _.first(_queryQueue); + _queryQueue = _.rest(_queryQueue); + + // still elements in queue + if (element) + { + _queryInProgress = element; + + if (_.isFunction(processFn)) + { + processFn(element); + } + } + // no more query to process + else + { + _queryInProgress = false; + } + } + + /** + * Function to be invoked upon completion of the process of a queue element. + */ + function complete() + { + _queryInProgress = false; + _dispatcher.trigger(_options.completeEvent); + } + + /** + * Adds a new element into the queue, and triggers a new request event. + * + * @param element a new queue element + */ + function add(element) + { + _queryQueue.push(element); + _dispatcher.trigger(_options.newRequestEvent); + } + + self.add = add; + self.complete = complete; + self.init = init; +} + +/* + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/** + * Singleton utility class for variant annotation related tasks. + * + * @author Selcuk Onur Sumer + */ +var VariantAnnotationUtil = (function() +{ + function addAnnotationData(mutations, annotationData, parseFn) + { + var indexedData = _.indexBy(annotationData, "variant"); + + if (!_.isFunction(parseFn)) + { + parseFn = defaultParseAnnotationData; + } + + _.each(mutations, function(mutation, idx) { + var annotation = indexedData[mutation.get("variantKey")]; + var parsed = null; + + // check if annotation has an id field + if (annotation && annotation.id) + { + parsed = parseFn(annotation); + } + // if no id field, then try the annotationJSON field + else if (annotation && annotation.annotationJSON) + { + parsed = parseFn(annotation.annotationJSON); + } + + if (parsed) + { + // only update undefined fields! + setUndefinedFields(mutation, parsed); + } + }); + } + + /** + * Updates only the undefined fields of the given mutation. + * + * @param mutation a MutationModel instance + * @param annotation annotation data for single variant + */ + function setUndefinedFields(mutation, annotation) + { + var update = {}; + + _.each(_.keys(annotation), function(fieldName) { + if (_.isUndefined(mutation.get(fieldName))) + { + update[fieldName] = annotation[fieldName]; + } + }); + + if (!_.isEmpty(update)) + { + mutation.set(update); + } + } + + /** + * Default parse function that retrieves the partial data from + * the raw annotation data. + * + * @param annotation raw annotation data (from VEP) + * @returns {object} parsed annotation data + */ + function defaultParseAnnotationData(annotation) + { + var vepData = VepParser.parseJSON(annotation); + var canonical = vepData.canonicalTranscript; + + // in case of empty annotation data (possible error), + // corresponding data fields will be empty string + + // TODO define a proper VariantAnnotation model instead? + var empty = { + startPos: "", + endPos: "", + chr: "", + referenceAllele: "", + variantAllele: "", + proteinChange: "" + }; + + // remove unused fields + delete(vepData.rawData); + delete(vepData.transcripts); + delete(vepData.refseqIds); + delete(vepData.canonicalTranscript); + + // copy canonical data properties + return _.extend(empty, vepData, canonical); + } + + /** + * Generates variant key for annotation queries. + * This function assumes that basic mutation data (chromosome number, + * start position, reference allele, variant allele) is available + * for the provided mutation. If not, returns undefined. + * + * Example keys: 10:g.152595854G>A + * 17:g.36002278_36002277insA + * 1:g.206811015_206811016delAC + * + * @param mutation mutation attributes or a MutationModel instance + * @returns {string|undefined} variant key (to be used for annotation query) + */ + function generateVariantKey(mutation) + { + var key = undefined; + + var chr = mutation.chr; + var startPos = mutation.startPos; + var endPos = mutation.endPos; + var referenceAllele = mutation.referenceAllele; + var variantAllele = mutation.variantAllele; + + // if mutation has a get function, assume that it is a MutationModel instance + if (_.isFunction(mutation.get)) + { + chr = mutation.get("chr"); + startPos = mutation.get("startPos"); + endPos = mutation.get("endPos"); + referenceAllele = mutation.get("referenceAllele"); + variantAllele = mutation.get("variantAllele"); + } + + if (referenceAllele != null && + referenceAllele === variantAllele) + { + console.log("[VariantAnnotationUtil.generateVariantKey] " + + "Warning: Reference allele (" + referenceAllele + ") for " + + chr + ":" + startPos + "-" + endPos + " is the same as variant allele"); + } + + function adjustPosition() + { + var start = parseInt(startPos); + var end = parseInt(endPos); + + if (_.isNaN(start) && _.isNaN(end)) + { + // start or end position is not a number, + // cannot process further + return; + } + + // remove common prefix and adjust variant position accordingly + + var prefix = cbio.util.lcss(referenceAllele, variantAllele); + + if (prefix.length > 0) + { + referenceAllele = referenceAllele.substring(prefix.length); + variantAllele = variantAllele.substring(prefix.length); + + start += prefix.length; + // TODO end position may already be correct + // (no need to update in that case) + end += prefix.length; + + startPos = start.toString(); + endPos = end.toString(); + } + } + + if (chr && startPos && referenceAllele && variantAllele) + { + adjustPosition(); + + // this is what we will end up with if there is no endPos is provided + // example SNP: 2 216809708 216809708 C T + // example key: 2:g.216809708C>T + key = chr + ":g." + startPos + referenceAllele + ">" + variantAllele; + + if (endPos) + { + // example insertion: 17 36002277 36002278 - A + // example key: 17:g.36002278_36002277insA + if (referenceAllele === "-" || + referenceAllele.length === 0) + { + key = chr+ ":g." + endPos + "_" + startPos + "ins" + variantAllele; + } + // Example deletion: 1 206811015 206811016 AC - + // Example key: 1:g.206811015_206811016delAC + else if(variantAllele === "-" || + variantAllele.length === 0) + { + key = chr + ":g." + startPos + "_" + endPos + "del" + referenceAllele; + } + } + } + + return key; + } + + return { + generateVariantKey: generateVariantKey, + addAnnotationData: addAnnotationData + }; +})(); + +/** + * Parses JSON Retrieved from VEP web service. + * + * @author Selcuk Onur Sumer + */ +var VepParser = (function() +{ + var _aa3to1 = { + "Ala": "A", + "Arg": "R", + "Asn": "N", + "Asp": "D", + "Asx": "B", + "Cys": "C", + "Glu": "E", + "Gln": "Q", + "Glx": "Z", + "Gly": "G", + "His": "H", + "Ile": "I", + "Leu": "L", + "Lys": "K", + "Met": "M", + "Phe": "F", + "Pro": "P", + "Ser": "S", + "Thr": "T", + "Trp": "W", + "Tyr": "Y", + "Val": "V", + "Xxx": "X", + "Ter": "*" + }; + + var _variantMap = { + "splice_acceptor_variant": "Splice_Site", + "splice_donor_variant": "Splice_Site", + "transcript_ablation": "Splice_Site", + "stop_gained": "Nonsense_Mutation", + "frameshift_variant": "Frame_Shift", + "stop_lost": "Nonstop_Mutation", + "initiator_codon_variant": "Translation_Start_Site", + "start_lost": "Translation_Start_Site", + "inframe_insertion": "In_Frame_Ins", + "inframe_deletion": "In_Frame_Del", + "missense_variant": "Missense_Mutation", + "protein_altering_variant": "Missense_Mutation", // TODO Not sure if this is correct + "coding_sequence_variant": "Missense_Mutation", + "conservative_missense_variant": "Missense_Mutation", + "rare_amino_acid_variant": "Missense_Mutation", + "transcript_amplification": "Intron", + "splice_region_variant": "Intron", + "intron_variant": "Intron", + "INTRAGENIC": "Intron", + "intragenic_variant": "Intron", + "incomplete_terminal_codon_variant": "Silent", + "synonymous_variant": "Silent", + "stop_retained_variant": "Silent", + "NMD_transcript_variant": "Silent", + "mature_miRNA_variant": "RNA", + "non_coding_exon_variant": "RNA", + "non_coding_transcript_exon_variant": "RNA", + "non_coding_transcript_variant": "RNA", + "nc_transcript_variant": "RNA", + "5_prime_UTR_variant": "5'UTR", + "5_prime_UTR_premature_start_codon_gain_variant": "5'UTR", + "3_prime_UTR_variant": "3'UTR", + "TF_binding_site_variant": "IGR", + "regulatory_region_variant": "IGR", + "regulatory_region": "IGR", + "intergenic_variant": "IGR", + "intergenic_region": "IGR", + "upstream_gene_variant": "5'Flank", + "downstream_gene_variant": "3'Flank", + "TFBS_ablation": "Targeted_Region", + "TFBS_amplification": "Targeted_Region", + "regulatory_region_ablation": "Targeted_Region", + "regulatory_region_amplification": "Targeted_Region", + "feature_elongation": "Targeted_Region", + "feature_truncation": "Targeted_Region" + }; + + /** + * Parses the raw annotation JSON object. + * + * @param annotation JSON object returned by the web service + * @return {object} parsed JSON, or null in case of an error + */ + function parseJSON(annotation) + { + var vepData = {}; + + if (!annotation) + { + console.log("[warning] VEP parser error"); + return {}; + } + else if (annotation.error) + { + console.log("[warning] VEP parser error: " + annotation.error); + return {}; + } + + // proceed in case of no JSON error + var alleleString = annotation["allele_string"]; + var alleles = alleleString.split("/", -1); + + if (alleles.length === 2) + { + vepData.referenceAllele = alleles[0]; + //vepData.put(AnnoMafProcessor.VEP_REFERENCE_ALLELE.toLowerCase(), alleles[0]); + //vepData.put(AnnoMafProcessor.VEP_TUMOR_SEQ_ALLELE.toLowerCase(), alleles[1]); + + //vepData.put(AnnoMafProcessor.VEP_VARIANT_TYPE.toLowerCase(), variantType); + vepData.variantType = getVariantType(alleles[0], alleles[1]); + } + + vepData.ncbiBuildNo = annotation["assembly_name"]; + vepData.chr = annotation["seq_region_name"]; + vepData.startPos = annotation["start"]; + vepData.endPos = annotation["end"]; + vepData.strand = strandSign(annotation["strand"]); + + var transcripts = annotation["transcript_consequences"]; + var mostSevereConsequence = annotation["most_severe_consequence"]; + + // parse all transcripts + vepData.transcripts = []; + _.each(transcripts, function(transcript, idx) { + vepData.transcripts.push( + parseTranscript(transcript, mostSevereConsequence, vepData.variantType)); + }); + + // TODO what to do in case no canonical transcript can be determined? + var canonicalTranscript = getCanonicalTranscript(transcripts, mostSevereConsequence); + + if (canonicalTranscript && + vepData.transcripts[canonicalTranscript.index]) + { + vepData.canonicalTranscript = vepData.transcripts[canonicalTranscript.index]; + } + + // also attach the original raw data + vepData.rawData = annotation; + + return vepData; + } + + function parseTranscript(transcript, mostSevereConsequence, variantType, vepData) + { + vepData = vepData || {}; + + vepData.geneSymbol = transcript["gene_symbol"]; + + // JsonNode variantAllele = transcript.path("variant_allele"); + // if (!variantAllele.isMissingNode()) { + // vepData.put(AnnoMafProcessor.VEP_TUMOR_SEQ_ALLELE.toLowerCase(), variantAllele.asText()); + // } + + var consequenceTerms = transcript["consequence_terms"]; + + if (consequenceTerms != null && + consequenceTerms.length > 0) + { + // TODO what if more than one consequence term? + var variantClass = variantClassification(consequenceTerms[0]); + + if(variantClass === "Frame_Shift") { + if (variantType != null && variantType === "INS") { + variantClass += "_Ins"; + } + else if (variantType === "DEL") { + variantClass += "_Del"; + } + } + + vepData.variantClassification = variantClass; + } + + var refseqIds = transcript["refseq_transcript_ids"]; + + if (refseqIds != null && + refseqIds.length > 0) + { + vepData.refseqIds = refseqIds; + } + + var hgvsc = transcript["hgvsc"]; + if (hgvsc != null) { + vepData.hgvsc = hgvsc.substr(hgvsc.indexOf(":")+1); + } + + var hgvsp = transcript["hgvsp"]; + if (hgvsp != null) + { + // TODO (p.%3D) ? + //if (hgvsp.indexOf("(p.%3D)") != -1) { + // vepData.put(AnnoMafProcessor.VEP_HGVSP.toLowerCase(), "p.="); + //} + + vepData.hgvsp = hgvsp.substr(hgvsp.indexOf(":")+1); + } + + vepData.transcriptId = transcript["transcript_id"]; + vepData.proteinPosStart = transcript["protein_start"]; + vepData.proteinPosEnd = transcript["protein_end"]; + vepData.codons = transcript["codons"]; + + // create a shorter HGVS protein format + var hgvspShort; + + if (hgvsp != null) + { + hgvspShort = hgvsp.substr(hgvsp.indexOf(":")+1); + + _.each(_.pairs(_aa3to1), function(pair, idx) { + hgvspShort = hgvspShort.replace(new RegExp(pair[0], 'g'), pair[1]); + }); + + vepData.hgvspShort = hgvspShort; + } + + if (mostSevereConsequence === "splice_acceptor_variant" || + mostSevereConsequence === "splice_donor_variant") + { + //Pattern pattern = Pattern.compile("^c.([0-9]+)*"); + //Matcher matcher = pattern.matcher(hgvsc.asText().substring(iHgsvc+1)); + + //if( matcher.find() ) { + // int cPos = Integer.parseInt(matcher.group(1)); + // if( cPos < 1 ) { + // cPos = 1; + // } + // + // var pPos = Integer.toString(( cPos + cPos % 3 ) / 3 ); + // + // vepData.hgvspShort = "p.X" + pPos + "_splice"; + //} + + if (vepData.hgvsc) + { + var match = /c\.([0-9]+)*/.exec(vepData.hgvsc); + + if (match && match.length == 2) + { + var cPos = parseInt(match[1]); + + if (cPos < 1) { + cPos = 1; + } + + var pPos = cPos + (cPos % 3) / 3; + + vepData.hgvspShort = "p.X" + pPos + "_splice"; + } + } + } + + if (mostSevereConsequence === "synonymous_variant") + { + hgvspShort = "p." + + transcript["amino_acids"] + + transcript["protein_start"] + + transcript["amino_acids"]; + + vepData.hgvspShort = hgvspShort; + } + + // set aliases + vepData.mutationType = vepData.variantClassification; + vepData.proteinChange = vepData.hgvspShort; + if (vepData.refseqIds && vepData.refseqIds.length > 0) { + // TODO is it okay to pick the first one as the default refseq id? + vepData.refseqMrnaId = vepData.refseqIds[0]; + } + + return vepData; + } + + /** + * Finds and returns the canonical transcript within the given transcript list. + * Returns null in case no canonical transcript can be determined. + * + * @param transcripts list of transcript nodes + * @param mostSevereConsequence + * @return {object} canonical transcript node + */ + function getCanonicalTranscript(transcripts, mostSevereConsequence) + { + var list = []; + + _.each(transcripts, function(transcript, idx) { + if (transcript["canonical"] == 1) + { + list.push({index: idx, transcript:transcript}); + } + }); + + // trivial case: only one transcript marked as canonical + if (list.length === 1) + { + return list[0]; + } + // more than one transcript is marked as canonical, + // use most severe consequence to decide which one to pick + // among the ones marked as canonical + else if (list.length > 1) + { + return transcriptWithMostSevereConsequence(list, mostSevereConsequence); + } + // no transcript is marked as canonical (list.size() == 0), + // use most severe consequence to decide which one to pick + // among all available transcripts + else + { + _.each(transcripts, function(transcript, idx) { + list.push({index: idx, transcript:transcript}); + }); + + return transcriptWithMostSevereConsequence(list, mostSevereConsequence); + } + } + + /** + * Finds and returns the transcript node which has the given + * most severe consequence in its consequence terms. Returns + * null in case no match. + * + * @param transcripts list of transcript nodes + * @param mostSevereConsequence most severe consequence + * @return transcript node containing most severe consequence + */ + function transcriptWithMostSevereConsequence(transcripts, mostSevereConsequence) + { + // default value is null in case of no match + var transcriptWithMSC = null; + + _.each(transcripts, function(ele, idx) { + var consequenceTerms = ele.transcript["consequence_terms"]; + + if (transcriptWithMSC == null && + consequenceTerms != null && + mostSevereConsequence != null) + { + _.each(consequenceTerms, function(consequence, idx) { + if (consequence.trim().toLowerCase() === + mostSevereConsequence.trim().toLowerCase()) + { + transcriptWithMSC = ele; + } + }); + } + }); + + return transcriptWithMSC; + } + + function getVariantType(refAllele, varAllele) + { + var refLength = refAllele.length; + var varLength = varAllele.length; + refLength = refAllele === "-" ? 0 : refLength; + varLength = varAllele === "-" ? 0 : varLength; + + if (refLength === varLength) { + var npType = ["SNP", "DNP", "TNP"]; + return (refLength < 3 ? npType[refLength - 1] : "ONP"); + } + else { + if (refLength < varLength) { + return "INS"; + } + else { + return "DEL"; + } + } + } + + function variantClassification(variant) + { + return _variantMap[variant.toLowerCase()]; + } + + function strandSign(strand) + { + var sign; + + if (strand == null || + strand === "+" || + strand === "-") + { + sign = strand; + } + else + { + if (strand < 0) + { + sign = "-"; + } + else if (strand > 0) + { + sign = "+"; + } + else + { + sign = strand; + } + } + + return sign; + } + + return { + parseJSON: parseJSON + }; +})(); + + +/* + * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/** + * Mutation Model. + * + * Current model is sufficient to visualize both the table and the diagram. + * Later we may add more data if necessary. + * + * @author Selcuk Onur Sumer + */ +var MutationModel = Backbone.Model.extend({ + // TODO update initialize method when all done! + _initialize: function(attributes) { + this.mutationId = attributes.mutationId; + this.mutationSid = attributes.mutationSid; + this.geneticProfileId = attributes.geneticProfileId; + this.mutationEventId = attributes.mutationEventId; + this.caseId = attributes.caseId; + this.geneSymbol = attributes.geneSymbol; + this.linkToPatientView = attributes.linkToPatientView; + this.cancerType = attributes.cancerType; + this.cancerStudy = attributes.cancerStudy; + this.cancerStudyShort = attributes.cancerStudyShort; + this.cancerStudyLink = attributes.cancerStudyLink; + this.tumorType = attributes.tumorType; + this.proteinChange = attributes.proteinChange; + this.aminoAcidChange = attributes.aminoAcidChange; + this.mutationType = attributes.mutationType; + this.cosmic = attributes.cosmic; + this.cosmicCount = this.calcCosmicCount(attributes.cosmic); + this.functionalImpactScore = attributes.functionalImpactScore; + this.fisValue = attributes.fisValue; + this.msaLink = attributes.msaLink; + this.xVarLink = attributes.xVarLink; + this.pdbLink = attributes.pdbLink; + this.pdbMatch = attributes.pdbMatch; // {pdbId, chainId} pair + this.igvLink = attributes.igvLink; + this.mutationStatus = attributes.mutationStatus; + this.validationStatus = attributes.validationStatus; + this.sequencingCenter = attributes.sequencingCenter; + this.ncbiBuildNo = attributes.ncbiBuildNo; + this.chr = attributes.chr; + this.startPos = attributes.startPos; + this.endPos = attributes.endPos; + this.referenceAllele = attributes.referenceAllele; + this.variantAllele = attributes.variantAllele; + this.tumorFreq = attributes.tumorFreq; + this.normalFreq = attributes.normalFreq; + this.tumorRefCount = attributes.tumorRefCount; + this.tumorAltCount = attributes.tumorAltCount; + this.normalRefCount = attributes.normalRefCount; + this.normalAltCount = attributes.normalAltCount; + this.canonicalTranscript = attributes.canonicalTranscript; + this.refseqMrnaId = attributes.refseqMrnaId; + this.codonChange = attributes.codonChange; + this.uniprotId = attributes.uniprotId; + this.uniprotAcc = attributes.uniprotAcc; + this.proteinPosStart = attributes.proteinPosStart; + this.proteinPosEnd = attributes.proteinPosEnd; + this.mutationCount = attributes.mutationCount; + this.specialGeneData = attributes.specialGeneData; + this.keyword = attributes.keyword; + this.cna = attributes.cna; + this.myCancerGenome = attributes.myCancerGenome; + this.isHotspot = attributes.isHotspot; + }, + url: function() { + // TODO implement this to get the data from a web service + var urlStr = "webservice.do?cmd=..."; + }, + /** + * Finds out the protein start position for this mutation. + * The field proteinPosStart has a priority over proteinChange. + * If none of these has a valid value, then this function + * returns null. + * + * @return protein start position + */ + getProteinStartPos: function() { // first try protein start pos - var position = this.proteinPosStart; + var position = this.get("proteinPosStart"); // if not valid, then try protein change value if (position == null || @@ -5492,8 +6580,13 @@ var MutationModel = Backbone.Model.extend({ getProteinChangeLocation: function() { var location = null; - var proteinChange = this.proteinChange; - var result = proteinChange.match(/[0-9]+/); + var result = null; + var proteinChange = this.get("proteinChange"); + + if (proteinChange != null) + { + result = proteinChange.match(/[0-9]+/); + } if (result && result.length > 0) { @@ -5502,6 +6595,23 @@ var MutationModel = Backbone.Model.extend({ return location; }, + getCosmicCount: function() + { + // if already set, return the current value + if (this.get("cosmicCount")) { + return this.get("cosmicCount"); + } + // if not set yet, calculate & set & return the value + else if (this.get("cosmic")) { + var cosmicCount = this.calcCosmicCount(this.get("cosmic")); + this.set({cosmicCount: cosmicCount}); + return cosmicCount; + } + // NA + else { + return null; + } + }, calcCosmicCount: function(cosmic) { var cosmicCount = 0; @@ -5576,7 +6686,8 @@ var PdbAlignmentModel = Backbone.Model.extend({ this.pdbTo = attributes.pdbTo; this.uniprotFrom = attributes.uniprotFrom; this.uniprotTo = attributes.uniprotTo; - this.alignmentString = attributes.alignmentString; + this.alignmentString = attributes.alignmentString || + PdbDataUtil.alignmentString(attributes); this.eValue = attributes.eValue; this.identityPerc = attributes.identityPerc; } @@ -6035,17 +7146,22 @@ var LollipopTipView = Backbone.View.extend({ * model: {geneSymbol: [hugo gene symbol], * mutationData: [mutation data for a specific gene] * dataProxies: [all available data proxies], - * sequence: [PFAM sequence data], - * sampleArray: [list of case ids as an array of strings], - * diagramOpts: [mutation diagram options -- optional], - * tableOpts: [mutation table options -- optional]} + * dataManager: global mutation data manager, + * uniprotId: uniprot identifier, + * sampleArray: [list of case ids as an array of strings]} * } * * @author Selcuk Onur Sumer */ var MainMutationView = Backbone.View.extend({ initialize : function (options) { - this.options = options || {}; + var defaultOpts = { + config: { + loaderImage: "images/ajax-loader.gif" + } + }; + + this.options = jQuery.extend(true, {}, defaultOpts, options); // custom event dispatcher this.dispatcher = {}; @@ -6056,8 +7172,7 @@ var MainMutationView = Backbone.View.extend({ // pass variables in using Underscore.js template var variables = {geneSymbol: self.model.geneSymbol, - mutationSummary: self._mutationSummary(), - uniprotId: self.model.sequence.metadata.identifier}; + uniprotId: self.model.uniprotId}; // compile the template using underscore var templateFn = BackboneTemplateCache.getTemplateFn("mutation_view_template"); @@ -6072,77 +7187,36 @@ var MainMutationView = Backbone.View.extend({ format: function() { var self = this; - // hide the mutation diagram filter info text by default + // initially hide all components by default + // they will be activated wrt selected options self.$el.find(".mutation-details-filter-info").hide(); self.$el.find(".mutation-details-no-data-info").hide(); + self.$el.find(".mutation-3d-initializer").hide(); + self.$el.find(".mutation-info-panel-container").hide(); + self.$el.find(".mutation-summary-view").hide(); + self.$el.find(".mutation-table-container").hide(); + self.$el.find(".mutation-diagram-view").hide(); }, - /** - * Initializes the main components (such as the mutation diagram - * and the table) of the view. - * - * @param mut3dVisView 3D visualizer view - * @return {Object} all components as a single object - */ - initComponents: function(mut3dVisView) + initPdbPanelView: function(pdbColl) { var self = this; - var gene = self.model.geneSymbol; - var mutationData = self.model.mutationData; - var dataProxies = self.model.dataProxies; - var sequence = self.model.sequence; - var diagramOpts = self.model.diagramOpts; - var tableOpts = self.model.tableOpts; - - // draw mutation diagram - var diagramView = self._initMutationDiagramView( - gene, mutationData, sequence, dataProxies, diagramOpts); - - var diagram = diagramView.mutationDiagram; - - var view3d = null; + var diagram = null; - // init 3D view if the diagram is initialized successfully - if (diagram) + // diagram can be null/disabled + if (self.diagramView && self.diagramView.mutationDiagram) { - if (mut3dVisView) - { - // init the 3d view - view3d = self._init3dView(gene, - sequence, - self.model.dataProxies.pdbProxy, - mut3dVisView); - } - } - else - { - console.log("Error initializing mutation diagram: %s", gene); + diagram = self.diagramView.mutationDiagram; } - // init mutation table view - var tableView = self._initMutationTableView(gene, mutationData, dataProxies, tableOpts); - - // update component references - self._mutationDiagram = diagram; - self._tableView = tableView; - self._mut3dView = view3d; - - return { - diagram: diagram, - tableView: tableView, - view3d: view3d - }; - }, - initPdbPanelView: function(pdbColl) - { - var self = this; - + // allow initializing the pdb panel even if there is no diagram var panelOpts = { //el: "#mutation_pdb_panel_view_" + gene.toUpperCase(), el: self.$el.find(".mutation-pdb-panel-view"), + config: {loaderImage: self.options.config.loaderImage}, model: {geneSymbol: self.model.geneSymbol, pdbColl: pdbColl, pdbProxy: self.model.dataProxies.pdbProxy}, - diagram: self._mutationDiagram + diagram: diagram }; var pdbPanelView = new PdbPanelView(panelOpts); @@ -6152,65 +7226,107 @@ var MainMutationView = Backbone.View.extend({ return pdbPanelView; }, - /** - * Generates a one-line summary of the mutation data. - * - * @return {string} summary string - */ - _mutationSummary: function() + initSummaryView: function() { var self = this; - var mutationUtil = self.model.dataProxies.mutationProxy.getMutationUtil(); - var gene = self.model.geneSymbol; - var cases = self.model.sampleArray; + var target = self.$el.find(".mutation-summary-view"); + target.show(); + + var summaryOpts = { + el: target, + model: { + mutationProxy: self.model.dataProxies.mutationProxy, + clinicalProxy: self.model.dataProxies.clinicalProxy, + geneSymbol: self.model.geneSymbol, + sampleArray: self.model.sampleArray + } + }; - var summary = ""; + var summaryView = new MutationSummaryView(summaryOpts); + summaryView.render(); - if (cases.length > 0) - { - // calculate somatic & germline mutation rates - var mutationCount = mutationUtil.countMutations(gene, cases); - // generate summary string for the calculated mutation count values - summary = mutationUtil.generateSummary(mutationCount); - } + self.summaryView = summaryView; - return summary; + return summaryView; + }, + init3dView: function(mut3dVisView) + { + var self = this; + + return self._init3dView(self.model.geneSymbol, + self.model.uniprotId, + self.model.dataProxies.pdbProxy, + mut3dVisView); }, /** * Initializes the 3D view initializer. * * @param gene - * @param sequence + * @param uniprotId * @param pdbProxy * @param mut3dVisView * @return {Object} a Mutation3dView instance */ - _init3dView: function(gene, sequence, pdbProxy, mut3dVisView) + _init3dView: function(gene, uniprotId, pdbProxy, mut3dVisView) { var self = this; - var view3d = null; - // init the 3d view - if (mut3dVisView) - { - view3d = new Mutation3dView({ - el: self.$el.find(".mutation-3d-initializer"), - model: {uniprotId: sequence.metadata.identifier, - geneSymbol: gene, - pdbProxy: pdbProxy} - }); + var target = self.$el.find(".mutation-3d-initializer"); + target.show(); - view3d.render(); + // init the 3d view (button) + var view3d = new Mutation3dView({ + el: target, + model: {uniprotId: uniprotId, + geneSymbol: gene, + pdbProxy: pdbProxy} + }); - // also reset (init) the 3D view if the 3D panel is already active - if (mut3dVisView.isVisible()) - { - view3d.resetView(); - } + view3d.render(); + + // also reset (init) the 3D view if the 3D panel is already active + if (mut3dVisView && + mut3dVisView.isVisible()) + { + view3d.resetView(); } return view3d; }, + /** + * Initializes the mutation diagram view for the given diagram options + * and sequence data. + * + * @param options mutation diagram options + * @param sequence PFAM sequence data + * @returns {MutationDiagramView} mutation diagram view instance + */ + initMutationDiagramView: function(options, sequence) + { + var self = this; + + //mutationData = mutationData || self.model.mutationData; + + self.diagramView = self._initMutationDiagramView( + self.model.geneSymbol, + self.model.mutationData, + sequence, + self.model.dataProxies, + options); + + if (!self.diagramView) + { + console.log("Error initializing mutation diagram: %s", self.model.geneSymbol); + } + else + { + self.dispatcher.trigger( + MutationDetailsEvents.DIAGRAM_INIT, + self.diagramView.mutationDiagram); + } + + return self.diagramView; + }, /** * Initializes the mutation diagram view. * @@ -6224,6 +7340,8 @@ var MainMutationView = Backbone.View.extend({ _initMutationDiagramView: function (gene, mutationData, sequenceData, dataProxies, options) { var self = this; + var target = self.$el.find(".mutation-diagram-view"); + target.show(); var model = {mutations: mutationData, sequence: sequenceData, @@ -6232,31 +7350,53 @@ var MainMutationView = Backbone.View.extend({ diagramOpts: options}; var diagramView = new MutationDiagramView({ - el: self.$el.find(".mutation-diagram-view"), + el: target, model: model}); diagramView.render(); return diagramView; }, + initMutationTableView: function(options) + { + var self = this; + + self.tableView = self._initMutationTableView(self.model.geneSymbol, + self.model.mutationData, + self.model.dataProxies, + self.model.dataManager, + options); + + if (!self.tableView) + { + console.log("Error initializing mutation table: %s", self.model.geneSymbol); + } + + return self.tableView; + }, /** * Initializes the mutation table view. * * @param gene hugo gene symbol * @param mutationData mutation data (array of JSON objects) * @param dataProxies all available data proxies + * @param dataManager global mutation data manager * @param options [optional] table options * @return {Object} initialized mutation table view */ - _initMutationTableView: function(gene, mutationData, dataProxies, options) + _initMutationTableView: function(gene, mutationData, dataProxies, dataManager, options) { var self = this; + var target = self.$el.find(".mutation-table-container"); + target.show(); var mutationTableView = new MutationDetailsTableView({ - el: self.$el.find(".mutation-table-container"), + el: target, + config: {loaderImage: self.options.config.loaderImage}, model: {geneSymbol: gene, mutations: mutationData, dataProxies: dataProxies, + dataManager: dataManager, tableOpts: options} }); @@ -6264,6 +7404,32 @@ var MainMutationView = Backbone.View.extend({ return mutationTableView; }, + initMutationInfoView: function(options) + { + var self = this; + var target = self.$el.find(".mutation-info-panel-container"); + target.show(); + + var model = { + mutations: self.model.mutationData, + infoPanelOpts: options + }; + + var infoView = new MutationInfoPanelView({ + el: target, + model: model + }); + + infoView.render(); + + self.infoView = infoView; + + self.dispatcher.trigger( + MutationDetailsEvents.INFO_PANEL_INIT, + self.infoView); + + return infoView; + }, /** * Initializes the filter reset link, which is a part of filter info * text on top of the diagram, with the given callback function. @@ -6588,7 +7754,14 @@ var Mutation3dVisInfoView = Backbone.View.extend({ */ var Mutation3dVisView = Backbone.View.extend({ initialize : function (options) { - this.options = options || {}; + var defaultOpts = { + config: { + loaderImage: "images/ajax-loader.gif", + helpImage: "images/help.png" + } + }; + + this.options = jQuery.extend(true, {}, defaultOpts, options); // custom event dispatcher this.dispatcher = {}; @@ -6600,10 +7773,11 @@ var Mutation3dVisView = Backbone.View.extend({ // compile the template using underscore var templateFn = BackboneTemplateCache.getTemplateFn("mutation_3d_vis_template"); - // TODO make the images customizable? - var template = templateFn( - {loaderImage: "images/ajax-loader.gif", - helpImage: "images/help.png"}); + + var template = templateFn({ + loaderImage: self.options.config.loaderImage, + helpImage: self.options.config.helpImage + }); // load the compiled HTML into the Backbone "el" self.$el.html(template); @@ -7531,7 +8705,7 @@ var MutationCustomizePanelView = Backbone.View.extend({ // template vars var variables = {minY: 2, - maxY: diagram.getMaxY()}; + maxY: diagram.getInitialMaxY()}; // compile the template using underscore var templateFn = BackboneTemplateCache.getTemplateFn("mutation_customize_panel_template"); @@ -7564,19 +8738,30 @@ var MutationCustomizePanelView = Backbone.View.extend({ }); // set initial value of the input field - var maxValY = diagram.getMaxY(); - yAxisInput.val(maxValY); + yAxisInput.val(diagram.getMaxY()); + + // init y-axis slider controls + yAxisSlider.slider({ + value: diagram.getMaxY(), // set value to current max + min: 2, // anything below 2 doesn't make much sense + max: diagram.getInitialMaxY(), // set max value to initial max + change: function(event, ui) { + var value = ui.value; + + // adjust the slider value to the threshold + // and stop execution, because this will trigger + // this event (change event) again... + if (value > diagram.getThreshold()) { + value = diagram.getThreshold(); + $(this).slider('value', value); + return; + } - // init y-axis slider controls - yAxisSlider.slider({value: maxValY, - min: 2, - max: maxValY, - change: function(event, ui) { // update input field - yAxisInput.val(ui.value); + yAxisInput.val(value); // update diagram - diagram.updateOptions({maxLengthY: ui.value}); + diagram.updateOptions({maxLengthY: value}); diagram.rescaleYAxis(); }, slide: function(event, ui) { @@ -7591,19 +8776,22 @@ var MutationCustomizePanelView = Backbone.View.extend({ if (event.keyCode == enterCode) { var input = yAxisInput.val(); + var value = input; // not a valid value, update with defaults - if (isNaN(input) || - input > maxValY || - input < 2) + if (isNaN(value) || + value > diagram.getThreshold()) { - yAxisInput.val(diagram.getMaxY()); + value = diagram.getThreshold(); } - // update weight slider position only if input is valid - else + else if (input < 2) { - yAxisSlider.slider("option", "value", Math.floor(input)); + value = 2; } + + // update weight slider and input value + yAxisInput.val(value); + yAxisSlider.slider("option", "value", Math.floor(value)); } }); }, @@ -7649,6 +8837,7 @@ var MutationCustomizePanelView = Backbone.View.extend({ * options: {el: [target container], * model: {mutations: mutation data as an array of JSON objects, * dataProxies: all available data proxies, + * dataManager: global mutation data manager * geneSymbol: hugo gene symbol as a string, * tableOpts: mutation table options (optional)} * } @@ -7657,7 +8846,13 @@ var MutationCustomizePanelView = Backbone.View.extend({ */ var MutationDetailsTableView = Backbone.View.extend({ initialize : function (options) { - this.options = options || {}; + var defaultOpts = { + config: { + loaderImage: "images/ajax-loader.gif" + } + }; + + this.options = jQuery.extend(true, {}, defaultOpts, options); // custom event dispatcher this.dispatcher = {}; @@ -7670,7 +8865,7 @@ var MutationDetailsTableView = Backbone.View.extend({ // compile the template using underscore var templateFn = BackboneTemplateCache.getTemplateFn("mutation_details_table_template"); // TODO customize loader image - var template = templateFn({loaderImage: "images/ajax-loader.gif"}); + var template = templateFn({loaderImage: self.options.config.loaderImage}); // load the compiled HTML into the Backbone "el" self.$el.html(template); @@ -7700,17 +8895,17 @@ var MutationDetailsTableView = Backbone.View.extend({ options, self.model.geneSymbol, mutationUtil, - self.model.dataProxies); + self.model.dataProxies, + self.model.dataManager); - // TODO self.mutationTable = table; - self.tableUtil = table; + self.mutationTable = table; if (_.isFunction(callback)) { callback(self, table); } - self._generateRowData(table.getColumnOptions(), mutationColl, function(rowData) { + self._generateRowData(table, table.getColumnOptions(), mutationColl, function(rowData) { // init table with the row data table.renderTable(rowData); // hide loader image @@ -7719,15 +8914,16 @@ var MutationDetailsTableView = Backbone.View.extend({ return table; }, - _generateRowData: function(headers, mutationColl, callback) + _generateRowData: function(table, headers, mutationColl, callback) { - // TODO make all additional ajax calls here? - var rows = []; mutationColl.each(function(mutation) { // only set the datum - var datum = {mutation: mutation}; + var datum = { + table: table, // reference to the actual table instance + mutation: mutation // actual mutation corresponding to the row + }; var row = [datum]; // set everything else to null... @@ -7768,7 +8964,7 @@ var MutationDetailsTableView = Backbone.View.extend({ for (var i = 0; i < mutations.length; i++) { //var row = tableSelector.find("#" + mutations[i].mutationId); - var row = tableSelector.find("tr." + mutations[i].mutationSid); + var row = tableSelector.find("tr." + mutations[i].get("mutationSid")); row.addClass("mutation-table-highlight"); } }, @@ -7793,14 +8989,14 @@ var MutationDetailsTableView = Backbone.View.extend({ filter: function(mutations, updateBox, limit) { var self = this; - var oTable = self.tableUtil.getDataTable(); + var oTable = self.mutationTable.getDataTable(); // construct regex var ids = []; for (var i = 0; i < mutations.length; i++) { - ids.push(mutations[i].mutationSid); + ids.push(mutations[i].get("mutationSid")); } var regex = "(" + ids.join("|") + ")"; @@ -7814,13 +9010,13 @@ var MutationDetailsTableView = Backbone.View.extend({ } // disable event triggering before filtering, otherwise it creates a chain reaction - self.tableUtil.setFilterEventActive(false); + self.mutationTable.setFilterEventActive(false); // apply filter self._applyFilter(oTable, regex, asRegex, updateBox, limit); // enable events after filtering - self.tableUtil.setFilterEventActive(true); + self.mutationTable.setFilterEventActive(true); }, /** * Resets all table filters (rolls back to initial state) @@ -7831,7 +9027,7 @@ var MutationDetailsTableView = Backbone.View.extend({ // pass an empty array to show everything self.filter([], true); // also clean filter related variables - self.tableUtil.cleanFilters(); + self.mutationTable.cleanFilters(); }, /** * Rolls back the table to the last state where a manual search @@ -7841,17 +9037,22 @@ var MutationDetailsTableView = Backbone.View.extend({ rollBack: function() { var self = this; - var oTable = self.tableUtil.getDataTable(); + var oTable = self.mutationTable.getDataTable(); // disable event triggering before filtering, otherwise it creates a chain reaction - self.tableUtil.setFilterEventActive(false); + self.mutationTable.setFilterEventActive(false); // re-apply last manual filter string - var searchStr = self.tableUtil.getManualSearch(); + var searchStr = self.mutationTable.getManualSearch(); self._applyFilter(oTable, searchStr, false); // enable events after filtering - self.tableUtil.setFilterEventActive(true); + self.mutationTable.setFilterEventActive(true); + }, + clearSearchBox: function() { + var self = this; + var searchBox = self.$el.find(".mutation_datatables_filter input[type=search]"); + searchBox.val(""); }, /** * Filters the given data table with the provided filter string. @@ -7881,14 +9082,15 @@ var MutationDetailsTableView = Backbone.View.extend({ var smartFilter = true; var caseInsensitive = true; - var prevValue = self.$el.find(".mutation_datatables_filter input[type=search]").val(); + var searchBox = self.$el.find(".mutation_datatables_filter input[type=search]"); + var prevValue = searchBox.val(); oTable.fnFilter(filterStr, limit, asRegex, smartFilter, updateBox, caseInsensitive); // reset to previous value if updateBox is set to false if (!updateBox) { - self.$el.find(".mutation_datatables_filter input[type=search]").val(prevValue); + searchBox.val(prevValue); } } }); @@ -7928,18 +9130,25 @@ var MutationDetailsTableView = Backbone.View.extend({ * Creates a separate MainMutationView (another Backbone view) for each gene. * * options: {el: [target container], - * model: {mutationProxy: [mutation data proxy], - * sampleArray: [list of case ids as an array of strings], - * diagramOpts: [mutation diagram options -- optional], - * tableOpts: [mutation table options -- optional]} - * mut3dVis: [optional] reference to the 3d structure visualizer + * model: {mutationProxy: [mutation data proxy]} * } * * @author Selcuk Onur Sumer */ var MutationDetailsView = Backbone.View.extend({ initialize : function (options) { - this.options = options || {}; + var defaultOpts = { + config: { + loaderImage: "images/ajax-loader.gif", + coreTemplate: "default_mutation_details_template", + mainContentTemplate: "default_mutation_details_main_content_template", + listContentTemplate: "default_mutation_details_list_content_template" + } + }; + + this.options = jQuery.extend(true, {}, defaultOpts, options); + + this._3dPanelInitialized = false; // custom event dispatcher this.dispatcher = {}; @@ -7948,18 +9157,14 @@ var MutationDetailsView = Backbone.View.extend({ render: function() { var self = this; - // init tab view flags (for each gene) - self.geneTabView = {}; - var content = self._generateContent(); - // TODO make the image customizable? - var variables = {loaderImage: "images/ajax-loader.gif", + var variables = {loaderImage: self.options.config.loaderImage, listContent: content.listContent, mainContent: content.mainContent}; // compile the template using underscore - var templateFn = BackboneTemplateCache.getTemplateFn("default_mutation_details_template"); + var templateFn = BackboneTemplateCache.getTemplateFn(self.options.config.coreTemplate); var template = templateFn(variables); // load the compiled HTML into the Backbone "el" @@ -7967,11 +9172,27 @@ var MutationDetailsView = Backbone.View.extend({ if (self.model.mutationProxy.hasData()) { - self._initDefaultView(); + if (_.isFunction(self.options.config.init)) + { + self.options.config.init(self); + } + else + { + // init default view, if no custom init function is provided + self._initDefaultView(); + } } // format after render - self.format(); + + if (self.options.config.format) + { + self.options.config.format(self); + } + else + { + self.format(); + } }, /** * Formats the contents of the view after the initial rendering. @@ -8007,6 +9228,21 @@ var MutationDetailsView = Backbone.View.extend({ // but the function doesn't have public access... $(window).trigger('resize'); }, + init3dPanel: function() + { + var self = this; + + self.dispatcher.trigger( + MutationDetailsEvents.VIS_3D_PANEL_INIT); + + self._3dPanelInitialized = true; + }, + is3dPanelInitialized: function() + { + var self = this; + + return self._3dPanelInitialized; + }, /** * Generates the content structure by creating div elements for each * gene. @@ -8021,14 +9257,14 @@ var MutationDetailsView = Backbone.View.extend({ // create a div for for each gene _.each(self.model.mutationProxy.getGeneList(), function(gene, idx) { - var templateFn = BackboneTemplateCache.getTemplateFn("default_mutation_details_main_content_template"); + var templateFn = BackboneTemplateCache.getTemplateFn(self.options.config.mainContentTemplate); mainContent += templateFn( - {loaderImage: "images/ajax-loader.gif", + {loaderImage: self.options.config.loaderImage, geneSymbol: gene, geneId: cbio.util.safeProperty(gene)}); - templateFn = BackboneTemplateCache.getTemplateFn("default_mutation_details_list_content_template"); + templateFn = BackboneTemplateCache.getTemplateFn(self.options.config.listContentTemplate); listContent += templateFn( {geneSymbol: gene, @@ -8120,6 +9356,7 @@ var MutationDetailsView = Backbone.View.extend({ * model: {mutations: [mutation data as an array of JSON objects], * sequence: [sequence data as an array of JSON objects], * geneSymbol: [hugo gene symbol as a string], + * dataProxies: all available data proxies, * diagramOpts: [mutation diagram options -- optional]} * } * @@ -8450,16 +9687,354 @@ var MutationHelpPanelView = Backbone.View.extend({ // format panel controls var helpClose = self.$el.find(".diagram-help-close"); - // add listener to close button - helpClose.click(function(event) { - event.preventDefault(); - self.toggleView(); - }); + // add listener to close button + helpClose.click(function(event) { + event.preventDefault(); + self.toggleView(); + }); + }, + toggleView: function() { + var self = this; + self.$el.slideToggle(); + } +}); + +/* + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/** + * Mutation Details Customization Panel View. + * + * This view is designed to provide a customization panel for Mutation Details page. + * + * options: {el: [target container], + * model: {}, + * } + * + * @author Selcuk Onur Sumer + */ +var MutationInfoPanelView = Backbone.View.extend({ + initialize : function (options) { + this.options = options || {}; + + // custom event dispatcher + this.dispatcher = {}; + _.extend(this.dispatcher, Backbone.Events); + + // initial count by type map + //this.initialMapByType = this._mapMutationsByType(this.model.mutations); + this.initialMapByType = this._mapMutationsByMainType(this.model.mutations); + //this.selectionMap = this.resetSelectionMap(); + }, + render: function() + { + var self = this; + self.updateView(self.model.mutations); + }, + format: function() + { + var self = this; + + self.$el.find(".mutation-type-info-link").on('click', function(evt) { + evt.preventDefault(); + var mutationType = $(this).attr("alt"); + + //if (self.selectionMap[mutationType] != null) + //{ + // self.selectionMap[mutationType] += 1; + //} + + self.dispatcher.trigger( + MutationDetailsEvents.INFO_PANEL_MUTATION_TYPE_SELECTED, + mutationType); + }); + }, + updateView: function(mutations) { + var self = this; + //self.currentMapByType = self._mapMutationsByType(mutations); + self.currentMapByType = self._mapMutationsByMainType(mutations); + var countByType = self._countMutationsByType(self.currentMapByType); + var mutationTypeStyle = MutationViewsUtil.getVisualStyleMaps().mutationType; + var content = []; + + countByType = _.extend(self._generateZeroCountMap(self.initialMapByType), countByType); + + // sort mutation types by priority + var keys = _.keys(countByType).sort(function(a, b) { + var priorityA = 1024; + var priorityB = 1024; + + if (mutationTypeStyle[a] && mutationTypeStyle[a].priority) { + priorityA = mutationTypeStyle[a].priority; + } + + if (mutationTypeStyle[b] && mutationTypeStyle[b].priority) { + priorityB = mutationTypeStyle[b].priority; + } + + return priorityA - priorityB; + }); + + _.each(keys, function(mutationType) { + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_info_panel_type_template"); + + var text = "Other"; + var textStyle = mutationTypeStyle["other"].style; + + var view = mutationTypeStyle[mutationType]; + + if (view && view.mainType) + { + view = mutationTypeStyle[view.mainType]; + } + + if (view) + { + text = view.longName || text; + textStyle = view.style || textStyle; + } + + var count = countByType[mutationType]; + + var variables = { + mutationType: mutationType, + type: text, + textStyle: textStyle, + count: count, + countStyle: textStyle + "_count" + }; + + var template = templateFn(variables); + content.push(template); + }); + + // template vars + var variables = { + mutationTypeContent: content.join("\n") + }; + + // compile the template using underscore + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_info_panel_template"); + var template = templateFn(variables); + + // load the compiled HTML into the Backbone "el" + self.$el.html(template); + + // format after rendering + self.format(); + }, + _generateZeroCountMap: function(mapByType) { + var zeroCountMap = {}; + + _.each(_.keys(mapByType), function (key) { + zeroCountMap[key] = 0; + }); + + return zeroCountMap; + }, + resetSelectionMap: function() { + var self = this; + + self.selectionMap = self._generateZeroCountMap(self.initialMapByType); + }, + // TODO move these into a utility class + _mapMutationsByType: function(mutations) { + return _.groupBy(mutations, function(mutation) { + return mutation.get("mutationType").toLowerCase(); + }); + }, + _mapMutationsByMainType: function(mutations) { + var mutationTypeStyle = MutationViewsUtil.getVisualStyleMaps().mutationType; + + return _.groupBy(mutations, function(mutation) { + var type = mutation.get("mutationType"); + if (type) { + type = type.toLowerCase(); + } + else { + type = "other"; + } + + var mainType; + + if (mutationTypeStyle[type]) { + mainType = mutationTypeStyle[type].mainType; + } + else { + mainType = "other"; + } + + return mainType; + }); + }, + _countMutationsByType: function(mapByType) { + var countByType = {}; + + _.each(_.keys(mapByType), function(type) { + countByType[type] = _.size(mapByType[type]); + }); + + return countByType; + } +}); + + +/* + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/** + * Mutation Details Customization Panel View. + * + * This view is designed to provide a customization panel for Mutation Details page. + * + * options: {el: [target container], + * model: {}, + * } + * + * @author Selcuk Onur Sumer + */ +var MutationSummaryView = Backbone.View.extend({ + initialize : function (options) { + this.options = options || {}; + + // custom event dispatcher + //this.dispatcher = {}; + //_.extend(this.dispatcher, Backbone.Events); + }, + render: function() + { + var self = this; + var mutationSummary; + + self.model.clinicalProxy.getPatientData(self.model.sampleArray, function(data) { + if (!data) { + mutationSummary = self._mutationSummary(); + } + else { + mutationSummary = self._germlineMutationSummary(data); + } + + var variables = { + mutationSummary: mutationSummary, + geneSymbol: self.model.geneSymbol + }; + + // compile the template using underscore + var templateFn = BackboneTemplateCache.getTemplateFn('mutation_summary_view_template'); + var template = templateFn(variables); + + // load the compiled HTML into the Backbone "el" + self.$el.html(template); + + self.format(); + }); + }, + format: function() + { + var self = this; + }, + /** + * Generates a one-line summary of the mutation data. + * + * @return {string} summary string + */ + _mutationSummary: function() + { + var self = this; + var mutationUtil = self.model.mutationProxy.getMutationUtil(); + var gene = self.model.geneSymbol; + var cases = self.model.sampleArray; + + var summary = ""; + + if (cases.length > 0) + { + // calculate somatic & germline mutation rates + var mutationCount = mutationUtil.countMutations(gene, cases); + // generate summary string for the calculated mutation count values + summary = mutationUtil.generateSummary(mutationCount); + } + + return summary; }, - toggleView: function() { - var self = this; - self.$el.slideToggle(); - } + _germlineMutationSummary: function(clinicalGermlineData) { + var self = this; + var mutationUtil = self.model.mutationProxy.getMutationUtil(); + var gene = self.model.geneSymbol; + var cases = self.model.sampleArray; + var numGermlineCases = 0; + var summary = ""; + + if(cases.length > 0) { + var mutationCount = mutationUtil.countMutations(gene, cases); + + for (var i = 0; i < clinicalGermlineData.length; i++) { + var clinicalData = clinicalGermlineData[i]; + if (clinicalData.attr_val === "YES") { + numGermlineCases++; + } + } + + mutationCount.numGermlineCases = numGermlineCases; + summary = mutationUtil.generateSummary(mutationCount); + } + + return summary; + } }); /* @@ -8718,7 +10293,13 @@ var PdbChainTipView = Backbone.View.extend({ */ var PdbPanelView = Backbone.View.extend({ initialize : function (options) { - this.options = options || {}; + var defaultOpts = { + config: { + loaderImage: "images/ajax-loader.gif" + } + }; + + this.options = jQuery.extend(true, {}, defaultOpts, options); this.collapseTimer = null; this.expandTimer = null; }, @@ -8802,6 +10383,7 @@ var PdbPanelView = Backbone.View.extend({ var tableOpts = { el: self.$el.find(".mutation-pdb-table-view"), + config: {loaderImage: self.options.config.loaderImage}, model: {geneSymbol: self.model.geneSymbol, pdbColl: pdbColl, pdbProxy: self.model.pdbProxy} @@ -9016,27 +10598,31 @@ var PdbPanelView = Backbone.View.extend({ _initPdbPanel: function() { var self = this; - var panel = null; var pdbColl = self.model.pdbColl; var pdbProxy = self.model.pdbProxy; var mutationDiagram = self.options.diagram; + var options = {el: self.$el.find(".mutation-pdb-panel-container"), + maxHeight: 200}; + var xScale = null; + + // if mutation diagram is enabled, + // get certain values from mutation diagram for consistent rendering! if (mutationDiagram != null) { - var xScale = mutationDiagram.xScale; + xScale = mutationDiagram.xScale; // set margin same as the diagram margin for correct alignment with x-axis - var options = {el: self.$el.find(".mutation-pdb-panel-container"), - marginLeft: mutationDiagram.options.marginLeft, - marginRight: mutationDiagram.options.marginRight, - maxHeight: 200}; - // init panel - panel = new MutationPdbPanel(options, pdbColl, pdbProxy, xScale); - panel.init(); + options.marginLeft = mutationDiagram.options.marginLeft; + options.marginRight = mutationDiagram.options.marginRight; } + // init panel + var panel = new MutationPdbPanel(options, pdbColl, pdbProxy, xScale); + panel.init(); + return panel; } }); @@ -9087,7 +10673,13 @@ var PdbPanelView = Backbone.View.extend({ */ var PdbTableView = Backbone.View.extend({ initialize : function (options) { - this.options = options || {}; + var defaultOpts = { + config: { + loaderImage: "images/ajax-loader.gif" + } + }; + + this.options = jQuery.extend(true, {}, defaultOpts, options); }, render: function(callback) { @@ -9095,8 +10687,7 @@ var PdbTableView = Backbone.View.extend({ // compile the template using underscore var templateFn = BackboneTemplateCache.getTemplateFn("pdb_table_view_template"); - // TODO customize loader image - var template = templateFn({loaderImage: "images/ajax-loader.gif"}); + var template = templateFn({loaderImage: self.options.config.loaderImage}); // load the compiled HTML into the Backbone "el" self.$el.html(template); @@ -9458,6 +11049,8 @@ function AbstractDataProxy(options) data: {} // actual data, will be used only if it is a full init, i.e {initMode: "full"} }; + self._queryQueue = new RequestQueue(); + // merge options with default options to use defaults for missing values self._options = jQuery.extend(true, {}, self._defaultOpts, options); @@ -9466,6 +11059,10 @@ function AbstractDataProxy(options) */ self.init = function() { + self._queryQueue.init(function(options) { + $.ajax(options); + }); + if (self.isFullInit()) { self.fullInit(self._options); @@ -9507,8 +11104,186 @@ function AbstractDataProxy(options) { return !(self._options.initMode.toLowerCase() === "lazy"); }; + + + /** + * This function ensures that at most only one ajax request is + * sent from a particular DataProxy instance. This is to prevent + * too many simultaneous requests. + * + * @ajaxOptions jQuery ajax options + */ + self.requestData = function(ajaxOptions) + { + var complete = ajaxOptions.complete; + + var defaultOpts = { + complete: function(request, status) + { + self._queryQueue.complete(); + + if (_.isFunction(complete)) + { + complete(request, status); + } + } + }; + + // extend options with default options + var options = jQuery.extend(true, {}, ajaxOptions, defaultOpts); + + self._queryQueue.add(options); + }; +} + +/* + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/** + * This class is designed to retrieve cBio Portal specific data on demand. + * + * @param options additional options + * + * @author Selcuk Onur Sumer + */ +function ClinicalDataProxy(options) +{ + var self = this; + + // default options + var _defaultOpts = { + servletName: "api/clinicaldata", + subService: { + patients: "patients" + } + }; + + // merge options with default options to use defaults for missing values + var _options = jQuery.extend(true, {}, _defaultOpts, options); + + // call super constructor to init options and other params + AbstractDataProxy.call(this, _options); + _options = self._options; + + // cache + var _data = {}; + + /** + * Initializes with full data. Once initialized with full data, + * this proxy class assumes that there will be no additional data. + * + * @param options data proxy options + */ + function fullInit(options) + { + _data = options.data; + } + + function getPatientData(samples, callback) + { + // TODO full init & cache... + + var cancerStudyId; + var patientSampleMap = {}; + var patientIds = []; + var querySession = null; + + // TODO we need to find a better way to plug portal data into MutationMapper! + // workaround: since QuerySession is actually live in cBioPortal + // we need to make sure that it doesn't break the standalone MutationMapper instances + try { + querySession = window.QuerySession; + } catch (e) { + // undefined reference: QuerySession + } + + if (querySession) { + cancerStudyId = querySession.cancer_study_ids[0]; + querySession.getPatientSampleIdMap().then(function (patientSampleMap){ + for (var i = 0; i < samples.length; i++) { + patientIds.push(patientSampleMap[samples[i]]); + } + makePatientData(); + }); + } + else { + cancerStudyId = window.cancer_study_id; + makePatientData(); + } + + function makePatientData() { + // no cancer study id or patient information... + if (!cancerStudyId || _.size(patientIds) === 0) + { + callback(null); + return; + } + + var args = {study_id:cancerStudyId, attribute_ids:["12_245_PARTC_CONSENTED"], patient_ids:patientIds}; + var arg_strings = []; + for (var k in args) { + if (args.hasOwnProperty(k)) { + arg_strings.push(k + '=' + [].concat(args[k]).join(",")); + } + } + + var arg_string = arg_strings.join("&") || "?"; + + var ajaxOpts = { + type: "POST", + url: _options.servletName + "/" + _options.subService.patients, + data: arg_string, + dataType: "json", + success: function(data) { + callback(data); + }, + error: function(data) { + callback(null); + } + }; + + self.requestData(ajaxOpts); + } + } + + // override required base functions + self.fullInit = fullInit; + + // class specific functions + self.getPatientData = getPatientData; } +// ClinicalDataProxy extends AbstractDataProxy... +ClinicalDataProxy.prototype = new AbstractDataProxy(); +ClinicalDataProxy.prototype.constructor = ClinicalDataProxy; + /* * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. * @@ -9577,58 +11352,246 @@ function MutationAlignerDataProxy(options) _maDataCache = options.data; } - function getMutationAlignerData(servletParams, callback) - { - // TODO allow more than one accession at a time? (see MutationDataProxy) - var pfamAccession = servletParams.pfamAccession; + function getMutationAlignerData(servletParams, callback) + { + // TODO allow more than one accession at a time? (see MutationDataProxy) + var pfamAccession = servletParams.pfamAccession; + + if (pfamAccession == null) + { + // no gene symbol provided, nothing to retrieve + callback(null); + return; + } + + // retrieve data from the server if not cached + if (_maDataCache[pfamAccession] == undefined) + { + if (self.isFullInit()) + { + callback(null); + return; + } + + // process & cache the raw data + var processData = function(data) { + _maDataCache[pfamAccession] = data; + + // forward the processed data to the provided callback function + callback(data); + }; + + // retrieve data from the servlet + var ajaxOpts = { + type: "POST", + url: _options.servletName, + data: servletParams, + success: processData, + dataType: "json" + }; + + self.requestData(ajaxOpts); + } + else + { + // data is already cached, just forward it + callback(_maDataCache[pfamAccession]); + } + } + + // override required base functions + self.fullInit = fullInit; + + // class specific functions + self.getMutationAlignerData = getMutationAlignerData; +} + +// MutationAlignerDataProxy extends AbstractDataProxy... +MutationAlignerDataProxy.prototype = new AbstractDataProxy(); +MutationAlignerDataProxy.prototype.constructor = MutationAlignerDataProxy; + +/** + * Global data manager for Mutation Data, and for other data proxies. + * + * @param options data manager options (proxies, views, etc.) + * + * @author Selcuk Onur Sumer + */ +function MutationDataManager(options) +{ + var _viewMap = {}; + + // default options + var _defaultOpts = { + dataFn: { + variantAnnotation: function(dataProxies, params, callback) { + //var mutations = params.mutationTable.getMutations(); + var mutations = params.mutations || params.mutationTable.getMutations(); + var annotationProxy = dataProxies.variantAnnotationProxy; + var variants = []; + + _.each(mutations, function(mutation, idx) { + var variantKey = mutation.get("variantKey") || + VariantAnnotationUtil.generateVariantKey(mutation); + + if (!_.isUndefined(variantKey)) + { + variants.push(variantKey); + } + }); + + if (variants.length > 0 && annotationProxy) + { + // make variants a comma separated list + variants = variants.join(","); + + annotationProxy.getAnnotationData(variants, function(annotationData) { + // enrich current mutation data with the annotation data + VariantAnnotationUtil.addAnnotationData(mutations, annotationData); + + if (_.isFunction(callback)) + { + callback(params); + } + }); + } + else if (_.isFunction(callback)) + { + callback(params); + } + }, + pdbMatch: function(dataProxies, params, callback) { + var mutations = params.mutations || params.mutationTable.getMutations(); + var gene = params.gene || params.mutationTable.getGene(); + var pdbProxy = dataProxies.pdbProxy; + //var uniprotId = params.uniprotId; + + // TODO this is not a safe way of getting the uniprot ID! + var mainView = _viewMap[gene]; + var uniprotId = mainView.model.uniprotId; + + if (mutations && pdbProxy && uniprotId) + { + pdbProxy.getPdbRowData(uniprotId, function(pdbRowData) { + PdbDataUtil.addPdbMatchData(mutations, pdbRowData); + + if (_.isFunction(callback)) + { + callback(params); + } + }); + } + else if (_.isFunction(callback)) + { + callback(params); + } + }, + cBioPortal: function(dataProxies, params, callback) { + var pancanProxy = dataProxies.pancanProxy; + var mutationUtil = params.mutationUtil || params.mutationTable.getMutationUtil(); + var mutations = params.mutations || params.mutationTable.getMutations(); + + // get the pancan data and update the data & display values + pancanProxy.getPancanData({cmd: "byProteinPos"}, mutationUtil, function(dataByPos) { + pancanProxy.getPancanData({cmd: "byHugos"}, mutationUtil, function(dataByGeneSymbol) { + var frequencies = PancanMutationDataUtil.getMutationFrequencies( + {protein_pos_start: dataByPos, hugo: dataByGeneSymbol}); + + // update mutation counts (cBioPortal data field) for each datum + _.each(mutations, function(ele, i) { + //var proteinPosStart = ele[indexMap["datum"]].mutation.get("proteinPosStart"); + var proteinPosStart = ele.get("proteinPosStart"); + + // update the value of the datum only if proteinPosStart value is valid + if (proteinPosStart > 0) + { + var value = PancanMutationDataUtil.countByKey(frequencies, proteinPosStart) || 0; + //ele[indexMap["datum"]].mutation.set({cBioPortal: value}); + ele.set({cBioPortal: value}); + } + else + { + //ele[indexMap["datum"]].mutation.set({cBioPortal: 0}); + ele.set({cBioPortal: 0}); + } + }); + + if (_.isFunction(callback)) + { + // frequencies is the custom data, that we should not attach to the + // mutation object directly, so passing it to the callback function + callback(params, frequencies); + } + }); + }); + } + }, + dataProxies : {} + }; + + // merge options with default options to use defaults for missing values + var _options = jQuery.extend(true, {}, _defaultOpts, options); - if (pfamAccession == null) - { - // no gene symbol provided, nothing to retrieve - callback(null); - return; - } + // list of request queues keyed by data request type + // pairs + var _requestManager = {}; - // retrieve data from the server if not cached - if (_maDataCache[pfamAccession] == undefined) + /** + * Retrieves the data for the given data type by invoking the corresponding + * data retrieval function + * + * @param type data type + * @param params params to be passed over the callback function + * @param callback callback function to be invoked after data retrieval + */ + function getData(type, params, callback) + { + // init a different queue for each distinct type + if (_requestManager[type] == null) { - if (self.isFullInit()) - { - callback(null); - return; - } + _requestManager[type] = new RequestQueue(); - // process & cache the raw data - var processData = function(data) { - _maDataCache[pfamAccession] = data; + // init with a custom request process function + _requestManager[type].init(function(element) { + // corresponding data retrieval function + var dataFn = _options.dataFn[element.type]; - // forward the processed data to the provided callback function - callback(data); - }; + if (_.isFunction(dataFn)) + { + // call the function, with a special callback + dataFn(_options.dataProxies, element.params, function(params, data) { + // call the actual callback function + element.callback(params, data); - // retrieve data from the servlet - $.getJSON(_options.servletName, - servletParams, - processData); - } - else - { - // data is already cached, just forward it - callback(_maDataCache[pfamAccession]); + // process of the current element complete + _requestManager[element.type].complete(); + }); + } + // no data function is registered for this data field + else + { + element.callback(element.params, null); + // process of the current element complete + _requestManager[type].complete(); + } + }); } + + // add the request to the corresponding queue. + // this helps preventing simultaneously requests to the server for the same type + // (NOTE: this does not check if the parameters are exactly the same or not) + _requestManager[type].add({type: type, params: params, callback: callback}); } - // override required base functions - self.fullInit = fullInit; + function addView(gene, mainView) + { + _viewMap[gene] = mainView; + } - // class specific functions - self.getMutationAlignerData = getMutationAlignerData; + this.getData = getData; + this.addView = addView; } -// MutationAlignerDataProxy extends AbstractDataProxy... -MutationAlignerDataProxy.prototype = new AbstractDataProxy(); -MutationAlignerDataProxy.prototype.constructor = MutationAlignerDataProxy; - /* * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. * @@ -9701,7 +11664,15 @@ function MutationDataProxy(options) function fullInit(options) { var data = options.data; - var mutations = new MutationCollection(data); + var mutations = data; + + // convert to a collection if required + // (if not an array, assuming it is a MutationCollection) + if (_.isArray(data)) + { + mutations = new MutationCollection(data); + } + _util.processMutationData(mutations); } @@ -9779,7 +11750,7 @@ function MutationDataProxy(options) // concat new data with already cached data, // and forward it to the callback function - mutationData = mutationData.concat(data); + mutationData = mutationData.concat(mutations.models); callback(mutationData); }; @@ -9794,7 +11765,7 @@ function MutationDataProxy(options) // retrieve data from the server //$.post(_options.servletName, servletParams, process, "json"); - $.ajax({ + var ajaxOpts = { type: "POST", url: _options.servletName, data: servletParams, @@ -9805,7 +11776,9 @@ function MutationDataProxy(options) process([]); }, dataType: "json" - }); + }; + + self.requestData(ajaxOpts); } // data for all requested genes already cached else @@ -9989,12 +11962,17 @@ function PancanMutationDataProxy(options) !self.isFullInit()) { // retrieve missing data from the servlet - $.getJSON(_options.servletName, - {cmd: cmd, q: toQuery.join(",")}, - function(response) { - processData(response, data, cache, fields, callback); - } - ); + var ajaxOpts = { + type: "POST", + url: _options.servletName, + data: {cmd: cmd, q: toQuery.join(",")}, + success: function(response) { + processData(response, data, cache, fields, callback); + }, + dataType: "json" + }; + + self.requestData(ajaxOpts); } // everything is already cached (or full init) else @@ -10142,7 +12120,16 @@ function PdbDataProxy(options) // default options var _defaultOpts = { - servletName: "get3dPdb.json", + //servletName: "get3dPdb.json", + servletName: "pdb_annotation", + subService: { + alignmentByPdb: "alignment/byPdb", + alignmentByUniprot: "alignment/byUniprot", + header: "header", + map: "map", + summary: "summary" + }, + listJoiner: ",", mutationUtil: {} // an instance of MutationDetailsUtil class }; @@ -10249,12 +12236,7 @@ function PdbDataProxy(options) }); // convert object to array - var positionData = []; - - for (var key in positionObj) - { - positionData.push(positionObj[key]); - } + var positionData = _.values(positionObj); // populate alignment data array var alignmentData = []; @@ -10268,21 +12250,38 @@ function PdbDataProxy(options) var positionMap = {}; var mutations = _util.getMutationGeneMap()[gene]; - if (data.positionMap != null) + // this is to be compatible with both old and the new services... + var positionData = data.positionMap || data; + + if (positionData != null && + _.size(positionData) > 0) { // re-map mutation ids with positions by using the raw position map for(var i=0; i < mutations.length; i++) { - var start = data.positionMap[mutations[i].getProteinStartPos()]; + var start = positionData[mutations[i].getProteinStartPos()]; + + // TODO if the data is an array pick the longest one... + if (_.isArray(start) && _.size(start) > 0) + { + start = start[0]; + } + var end = start; - var type = mutations[i].mutationType; + var type = mutations[i].get("mutationType"); // ignore end position for mutation other than in frame del if (type != null && type.toLowerCase() === "in_frame_del") { - end = data.positionMap[mutations[i].proteinPosEnd] || end; + end = positionData[mutations[i].get("proteinPosEnd")] || end; + + // TODO if array pick the longest one... + if (_.isArray(end) && _.size(end) > 0) + { + end = end[0]; + } } // if no start and end position found for this mutation, @@ -10290,7 +12289,7 @@ function PdbDataProxy(options) if (start != null && end != null) { - positionMap[mutations[i].mutationId] = + positionMap[mutations[i].get("mutationId")] = {start: start, end: end}; } } @@ -10310,11 +12309,27 @@ function PdbDataProxy(options) // check if there are positions to map if (positionData.length > 0) { + var url = _options.servletName; + + // this is to be compatible with both old and the new services... + if (_options.subService && _options.subService.map) + { + url = url + "/" + _options.subService.map; + } + // get pdb data for the current mutations - $.getJSON(_options.servletName, - {positions: positionData.join(" "), - alignments: alignmentData.join(" ")}, - processData); + var ajaxOpts = { + type: "POST", + url: url, + data: { + positions: positionData.join(_options.listJoiner), + alignments: alignmentData.join(_options.listJoiner) + }, + success: processData, + dataType: "json" + }; + + self.requestData(ajaxOpts); } // no position data: no need to query the server else @@ -10373,10 +12388,24 @@ function PdbDataProxy(options) callback(pdbColl); }; - // retrieve data from the servlet - $.getJSON(_options.servletName, - {uniprotId: uniprotId}, - processData); + var url = _options.servletName; + + if (_options.subService && + _options.subService.alignmentByUniprot) + { + url = url + "/" + _options.subService.alignmentByUniprot; + } + + //retrieve data from the servlet + var ajaxOpts = { + type: "POST", + url: url, + data: {uniprotId: uniprotId, uniprotIds: uniprotId}, + success: processData, + dataType: "json" + }; + + self.requestData(ajaxOpts); } else { @@ -10433,16 +12462,42 @@ function PdbDataProxy(options) { // process & cache the raw data var processData = function(data) { - _pdbDataSummaryCache[uniprotId] = data; + var summaryData = data; + + if (_.isArray(summaryData) && + _.size(summaryData) > 0) + { + summaryData = summaryData[0]; + } + + _pdbDataSummaryCache[uniprotId] = summaryData; // forward the processed data to the provided callback function - callback(data); + callback(summaryData); }; + var url = _options.servletName; + + if (_options.subService && + _options.subService.summary) + { + url = url + "/" + _options.subService.summary; + } + // retrieve data from the servlet - $.getJSON(_options.servletName, - {uniprotId: uniprotId, type: "summary"}, - processData); + var ajaxOpts = { + type: "POST", + url: url, + data: { + uniprotId: uniprotId, + uniprotIds: uniprotId, + type: "summary" + }, + success: processData, + dataType: "json" + }; + + self.requestData(ajaxOpts); } else { @@ -10520,14 +12575,20 @@ function PdbDataProxy(options) { // process & cache the raw data var processData = function(data) { + var pdbInfoData = data; + + if (_.isArray(data)) + { + pdbInfoData = _.indexBy(data, 'pdbId'); + } _.each(pdbIds, function(pdbId, idx) { - if (data[pdbId] != null) + if (pdbInfoData[pdbId] != null) { - _pdbInfoCache[pdbId] = data[pdbId]; + _pdbInfoCache[pdbId] = pdbInfoData[pdbId]; // concat new data with already cached data - pdbData[pdbId] = data[pdbId]; + pdbData[pdbId] = pdbInfoData[pdbId]; } }); @@ -10536,11 +12597,26 @@ function PdbDataProxy(options) }; // add pdbToQuery to the servlet params - servletParams.pdbIds = pdbToQuery.join(" "); + servletParams.pdbIds = pdbToQuery.join(_options.listJoiner); + + var url = _options.servletName; + + if (_options.subService && + _options.subService.header) + { + url = url + "/" + _options.subService.header; + } // retrieve data from the server - $.post(_options.servletName, servletParams, processData, "json"); - //$.getJSON(_options.servletName, servletParams, processData, "json"); + var ajaxOpts = { + type: "POST", + url: url, + data: servletParams, + success: processData, + dataType: "json" + }; + + self.requestData(ajaxOpts); } // data for all requested chains already cached else @@ -10630,7 +12706,7 @@ function PfamDataProxy(options) function fullInit(options) { //assuming the given data is a map of pairs - _pfamDataCache = options.data;; + _pfamDataCache = options.data; } function getPfamData(servletParams, callback) @@ -10663,9 +12739,15 @@ function PfamDataProxy(options) }; // retrieve data from the servlet - $.getJSON(_options.servletName, - servletParams, - processData); + var ajaxOpts = { + type: "POST", + url: _options.servletName, + data: servletParams, + success: processData, + dataType: "json" + }; + + self.requestData(ajaxOpts); } else { @@ -10798,9 +12880,15 @@ function PortalDataProxy(options) else { // retrieve data from the servlet - $.getJSON(_options.servletName, - queryParams, - processData); + var ajaxOpts = { + type: "POST", + url: _options.servletName, + data: queryParams, + success: processData, + dataType: "json" + }; + + self.requestData(ajaxOpts); } } @@ -10815,6 +12903,208 @@ function PortalDataProxy(options) PortalDataProxy.prototype = new AbstractDataProxy(); PortalDataProxy.prototype.constructor = PortalDataProxy; +/* + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/** + * This class is designed to retrieve annotation data on demand, + * but it can be also initialized with the full annotation data. + * + * @param options proxy options + * + * @author Selcuk Onur Sumer + */ +function VariantAnnotationDataProxy(options) +{ + var self = this; + + // map of pairs + var _annotationDataCache = {}; + + // default options + var _defaultOpts = { + servletName: "variant_annotation/hgvs" + }; + + // merge options with default options to use defaults for missing values + var _options = jQuery.extend(true, {}, _defaultOpts, options); + + // call super constructor to init options and other params + AbstractDataProxy.call(this, _options); + _options = self._options; + + /** + * Initializes with full annotation data. Once initialized with full data, + * this proxy class assumes that there will be no additional data. + * + * @param options data proxy options + */ + function fullInit(options) + { + //assuming the given data is a map of pairs + _annotationDataCache = options.data; + } + + /** + * Returns the mutation data for the given gene(s). + * + * @param variantList list of variants as a comma separated string + * @param callback callback function to be invoked after retrieval + */ + function getAnnotationData(variantList, callback) + { + var variants = variantList.trim().split(","); + var variantsToQuery = []; + + // get previously grabbed data (if any) + var annotationData = []; + + // process each variant in the given list + _.each(variants, function(variant, idx) { + // variant annotator is case sensitive! + //variant = variant.toUpperCase(); + + var data = _annotationDataCache[variant]; + + if (data == undefined || _.isEmpty(data)) + { + // annotation data does not exist for this variant, add it to the list + variantsToQuery.push(variant); + } + else + { + // data is already cached for this variant, update the data array + annotationData = annotationData.concat(data); + } + }); + + // all data is already retrieved (full init) + if (self.isFullInit()) + { + // just forward the call the callback function + callback(annotationData); + } + // we need to retrieve missing data (lazy init) + else + { + var process = function(data) { + // cache data (assuming data is an array) + _.each(data, function(variant, idx) { + // parse annotation JSON string + processAnnotationJSON(variant); + + // first check if variant.id exists + if (variant.id) + { + _annotationDataCache[variant.id] = variant; + } + // if not then try annotationJSON + else if (variant.annotationJSON.id) + { + _annotationDataCache[variant.annotationJSON.id] = variant; + } + }); + + // concat new data with already cached data, + // and forward it to the callback function + annotationData = annotationData.concat(data); + callback(annotationData); + }; + + // some (or all) data is missing, + // send ajax request for missing genes + if (variantsToQuery.length > 0) + { + var variantsData = variantsToQuery.join(","); + // retrieve data from the server + //$.post(_options.servletName, servletParams, process, "json"); + var ajaxOpts = { + type: "POST", + url: _options.servletName, + data: {variants: variantsData}, + success: process, + error: function() { + console.log("[VariantDataProxy.getAnnotationData] " + + "error retrieving annotation data for variants: " + + variantsData); + process([]); + }, + //processData: false, + //contentType: false, + dataType: "json" + }; + + self.requestData(ajaxOpts); + } + // data for all requested genes already cached + else + { + // just forward the data to the callback function + callback(annotationData); + } + } + } + + /** + * Processes the annotationJSON string and converts it to a regular JSON. + * + * @param variant variant to process + */ + function processAnnotationJSON(variant) + { + if (_.isString(variant.annotationJSON)) + { + // assuming it is a JSON string + var annotation = JSON.parse(variant.annotationJSON); + + if (_.isArray(annotation) && + annotation.length > 0) + { + annotation = annotation[0]; + } + + variant.annotationJSON = annotation; + } + } + + // override required base functions + self.fullInit = fullInit; + + // class specific functions + self.getAnnotationData = getAnnotationData; +} + +// VariantAnnotationDataProxy extends AbstractDataProxy... +VariantAnnotationDataProxy.prototype = new AbstractDataProxy(); +VariantAnnotationDataProxy.prototype.constructor = VariantAnnotationDataProxy; + /* * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. * @@ -10918,10 +13208,6 @@ function AdvancedDataTable(options) // in addition to the default source, type, and val parameters, // another parameter "indexMap" will also be passed to the function. columnData: {}, - // optional data retrieval functions for the additional data. - // these functions can be used to retrieve more data via ajax calls, - // to update the table on demand. - additionalData: {}, // default tooltip functions columnTooltips: {}, // default event listener config @@ -11128,26 +13414,6 @@ function AdvancedDataTable(options) }); }; - self._loadAdditionalData = function(helper) - { - helper = helper || {}; - - var tableSelector = $(self._options.el); - - _.each(_.keys(self._options.additionalData), function(key) { - // do not retrieve data for excluded columns - if (self._visiblityMap[key] != "excluded") - { - var dataFn = self._options.additionalData[key]; - - if (_.isFunction(dataFn)) - { - dataFn(helper); - } - } - }); - }; - self.getColumnOptions = function() { return self._options.columns; @@ -11158,6 +13424,11 @@ function AdvancedDataTable(options) return self._dataTable; }; + self.setDataTable = function(dataTable) + { + self._dataTable = dataTable; + }; + self.getIndexMap = function() { return _indexMap; @@ -11620,8 +13891,7 @@ function Mutation3dVis(name, options) var color = options.mutationColor; // update the residue selection map wrt mutation color mapper - for (var mutationId in chain.positionMap) - { + _.each(_.keys(chain.positionMap), function(mutationId) { var position = chain.positionMap[mutationId]; if (_.isFunction(options.mutationColorMapper)) @@ -11629,25 +13899,26 @@ function Mutation3dVis(name, options) color = options.mutationColorMapper(mutationId, pdbId, chain); } - if (color == null) + // do not color at all if the color is null, + // this automatically hides user-filtered mutations + // TODO but this also hides unmapped mutations (if any) + if (color != null) { - //color = defaultOpts.mutationColor; - - // do not color at all, this automatically hides user-filtered mutations - // TODO but this also hides unmapped mutations (if any) - continue; - } + if (colorMap[color] == null) + { + // using an object instead of an array (to avoid duplicates) + colorMap[color] = {}; + } - if (colorMap[color] == null) - { - // using an object instead of an array (to avoid duplicates) - colorMap[color] = {}; + var scriptPos = scriptGen.scriptPosition(position); + colorMap[color][scriptPos] = scriptPos; + mappedMutations.push(mutationId); } - - var scriptPos = scriptGen.scriptPosition(position); - colorMap[color][scriptPos] = scriptPos; - mappedMutations.push(mutationId); - } + //else + //{ + // color = defaultOpts.mutationColor; + //} + }); // convert maps to arrays _.each(colorMap, function(value, key, list) { @@ -11733,7 +14004,7 @@ function Mutation3dVis(name, options) // assuming all other mutations in the same pileup have // the same (or very close) mutation position. - var id = pileup.mutations[0].mutationId; + var id = pileup.mutations[0].get("mutationId"); // get script var script = generateFocusScript(id); @@ -11808,7 +14079,7 @@ function Mutation3dVis(name, options) _.each(pileups, function(pileup, i) { // assuming all other mutations in the same pileup have // the same (or very close) mutation position. - var id = pileup.mutations[0].mutationId; + var id = pileup.mutations[0].get("mutationId"); var position = _chain.positionMap[id]; if (position != null) @@ -12127,11 +14398,12 @@ function Mutation3dVis(name, options) * @param gene hugo gene symbol * @param mutationUtil mutation details util * @param dataProxies all available data proxies + * @param dataManager mutation data manager for additional data requests * @constructor * * @author Selcuk Onur Sumer */ -function MutationDetailsTable(options, gene, mutationUtil, dataProxies) +function MutationDetailsTable(options, gene, mutationUtil, dataProxies, dataManager) { var self = this; @@ -12353,7 +14625,8 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) return "visible"; } else { - return "excluded"; + //return "excluded"; + return "hidden"; } }, "mutationStatus": function (util, gene) { @@ -12382,7 +14655,8 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) return "hidden"; } else { // if (count <= 0) - return "excluded"; + //return "excluded"; + return "hidden"; } }, //"cBioPortal": function (util, gene) { @@ -12417,18 +14691,26 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) columnRender: { "mutationId": function(datum) { var mutation = datum.mutation; - return mutation.mutationId; + var value = mutation.get("mutationId"); + if (value === undefined) { + return ""; + } + return value; //return (mutation.mutationId + "-" + mutation.mutationSid); }, "mutationSid": function(datum) { var mutation = datum.mutation; - return mutation.mutationSid; + var value = mutation.get("mutationSid"); + if (value === undefined) { + return ""; + } + return value; }, "caseId": function(datum) { var mutation = datum.mutation; - var caseIdFormat = MutationDetailsTableFormatter.getCaseId(mutation.caseId); + var caseIdFormat = MutationDetailsTableFormatter.getCaseId(mutation.get("caseId")); var vars = {}; - vars.linkToPatientView = mutation.linkToPatientView; + vars.linkToPatientView = mutation.get("linkToPatientView"); vars.caseId = caseIdFormat.text; vars.caseIdClass = caseIdFormat.style; vars.caseIdTip = caseIdFormat.tip; @@ -12438,24 +14720,44 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) }, "proteinChange": function(datum) { var mutation = datum.mutation; - var proteinChange = MutationDetailsTableFormatter.getProteinChange(mutation); - var vars = {}; - vars.proteinChange = proteinChange.text; - vars.proteinChangeClass = proteinChange.style; - vars.proteinChangeTip = proteinChange.tip; - vars.additionalProteinChangeTip = proteinChange.additionalTip; - vars.pdbMatchLink = MutationDetailsTableFormatter.getPdbMatchLink(mutation); - var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_protein_change_template"); - return templateFn(vars); + // check if data exists, + // if not we need to retrieve it from the data manager + if (_.isUndefined(mutation.get("proteinChange"))) + { + self.requestColumnData("variantAnnotation", "proteinChange"); + return MutationViewsUtil.renderTablePlaceHolder(); + } + else + { + var proteinChange = MutationDetailsTableFormatter.getProteinChange(mutation); + var vars = {}; + + vars.proteinChange = proteinChange.text; + vars.proteinChangeClass = proteinChange.style; + vars.proteinChangeTip = proteinChange.tip; + vars.additionalProteinChangeTip = proteinChange.additionalTip; + + // check if pdbMatch data exists, + // if not we need to retrieve it from the data manager + if (_.isUndefined(mutation.get("pdbMatch"))) + { + self.requestColumnData("pdbMatch", "proteinChange"); + } + + vars.pdbMatchLink = MutationDetailsTableFormatter.getPdbMatchLink(mutation); + + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_protein_change_template"); + return templateFn(vars); + } }, "cancerStudy": function(datum) { var mutation = datum.mutation; var vars = {}; //vars.cancerType = mutation.cancerType; - vars.cancerStudy = mutation.cancerStudy; - vars.cancerStudyShort = mutation.cancerStudyShort; - vars.cancerStudyLink = mutation.cancerStudyLink; + vars.cancerStudy = mutation.get("cancerStudy"); + vars.cancerStudyShort = mutation.get("cancerStudyShort"); + vars.cancerStudyLink = mutation.get("cancerStudyLink"); var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_cancer_study_template"); return templateFn(vars); @@ -12473,51 +14775,82 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) }, "mutationType": function(datum) { var mutation = datum.mutation; - var mutationType = MutationDetailsTableFormatter.getMutationType(mutation.mutationType); - var vars = {}; - vars.mutationTypeClass = mutationType.style; - vars.mutationTypeText = mutationType.text; - var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_mutation_type_template"); - return templateFn(vars); + // check if data exists, + // if not we need to retrieve it from the data manager + if (_.isUndefined(mutation.get("mutationType"))) + { + self.requestColumnData("variantAnnotation", "mutationType"); + return MutationViewsUtil.renderTablePlaceHolder(); + } + else + { + var mutationType = MutationDetailsTableFormatter.getMutationType(mutation.get("mutationType")); + var vars = {}; + vars.mutationTypeClass = mutationType.style; + vars.mutationTypeText = mutationType.text; + + // 508 compliance to prevent empty label tag + if(_.isEmpty(mutationType.text)) { + return ""; + } + + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_mutation_type_template"); + return templateFn(vars); + } }, "cosmic": function(datum) { var mutation = datum.mutation; - var cosmic = MutationDetailsTableFormatter.getCosmic(mutation.cosmicCount); + var cosmic = MutationDetailsTableFormatter.getCosmic(mutation.getCosmicCount()); var vars = {}; vars.cosmicClass = cosmic.style; vars.cosmicCount = cosmic.count; + // 508 compliance to prevent empty label tag + if(_.isEmpty(cosmic.count)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_cosmic_template"); return templateFn(vars); }, "cna": function(datum) { var mutation = datum.mutation; - var cna = MutationDetailsTableFormatter.getCNA(mutation.cna); + var cna = MutationDetailsTableFormatter.getCNA(mutation.get("cna")); var vars = {}; vars.cna = cna.text; vars.cnaClass = cna.style; vars.cnaTip = cna.tip; + // 508 compliance to prevent empty label tag + if(_.isEmpty(cna.text)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_cna_template"); return templateFn(vars); }, "mutationCount": function(datum) { var mutation = datum.mutation; - var mutationCount = MutationDetailsTableFormatter.getIntValue(mutation.mutationCount); + var mutationCount = MutationDetailsTableFormatter.getIntValue(mutation.get("mutationCount")); var vars = {}; vars.mutationCount = mutationCount.text; vars.mutationCountClass = mutationCount.style; + // 508 compliance to prevent empty label tag + if(_.isEmpty(mutationCount.text)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_mutation_count_template"); return templateFn(vars); }, "normalFreq": function(datum) { var mutation = datum.mutation; - var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.normalAltCount); - var normalFreq = MutationDetailsTableFormatter.getAlleleFreq(mutation.normalFreq, - mutation.normalAltCount, - mutation.normalRefCount, + var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.get("normalAltCount")); + var normalFreq = MutationDetailsTableFormatter.getAlleleFreq(mutation.get("normalFreq"), + mutation.get("normalAltCount"), + mutation.get("normalRefCount"), "simple-tip"); var vars = {}; vars.normalFreq = normalFreq.text; @@ -12526,15 +14859,20 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) vars.normalTotalCount = normalFreq.total; vars.normalAltCount = alleleCount.text; + // 508 compliance to prevent empty label tag + if(_.isEmpty(normalFreq.text)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_normal_freq_template"); return templateFn(vars); }, "tumorFreq": function(datum) { var mutation = datum.mutation; - var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.tumorAltCount); - var tumorFreq = MutationDetailsTableFormatter.getAlleleFreq(mutation.tumorFreq, - mutation.tumorAltCount, - mutation.tumorRefCount, + var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.get("tumorAltCount")); + var tumorFreq = MutationDetailsTableFormatter.getAlleleFreq(mutation.get("tumorFreq"), + mutation.get("tumorAltCount"), + mutation.get("tumorRefCount"), "simple-tip"); var vars = {}; vars.tumorFreq = tumorFreq.text; @@ -12543,118 +14881,227 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) vars.tumorTotalCount = tumorFreq.total; vars.tumorAltCount = alleleCount.text; + // 508 compliance to prevent empty label tag + if(_.isEmpty(tumorFreq.text)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_tumor_freq_template"); return templateFn(vars); }, "mutationAssessor": function(datum) { var mutation = datum.mutation; var fis = MutationDetailsTableFormatter.getFis( - mutation.functionalImpactScore, mutation.fisValue); + mutation.get("functionalImpactScore"), mutation.get("fisValue")); var vars = {}; vars.fisClass = fis.fisClass; vars.omaClass = fis.omaClass; vars.fisText = fis.text; + // 508 compliance to prevent empty label tag + if(_.isEmpty(fis.text)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_mutation_assessor_template"); return templateFn(vars); }, "mutationStatus": function(datum) { var mutation = datum.mutation; - var mutationStatus = MutationDetailsTableFormatter.getMutationStatus(mutation.mutationStatus); + var mutationStatus = MutationDetailsTableFormatter.getMutationStatus(mutation.get("mutationStatus")); var vars = {}; vars.mutationStatusTip = mutationStatus.tip; vars.mutationStatusClass = mutationStatus.style; vars.mutationStatusText = mutationStatus.text; + // 508 compliance to prevent empty label tag + if(_.isEmpty(mutationStatus.text)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_mutation_status_template"); return templateFn(vars); }, "validationStatus": function(datum) { var mutation = datum.mutation; - var validationStatus = MutationDetailsTableFormatter.getValidationStatus(mutation.validationStatus); + var validationStatus = MutationDetailsTableFormatter.getValidationStatus(mutation.get("validationStatus")); var vars = {}; vars.validationStatusTip = validationStatus.tip; vars.validationStatusClass = validationStatus.style; vars.validationStatusText = validationStatus.text; + // 508 compliance to prevent empty label tag + if(_.isEmpty(validationStatus.text)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_validation_status_template"); return templateFn(vars); }, "normalRefCount": function(datum) { var mutation = datum.mutation; - var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.normalRefCount); + var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.get("normalRefCount")); var vars = {}; vars.normalRefCount = alleleCount.text; vars.normalRefCountClass = alleleCount.style; + // 508 compliance to prevent empty label tag + if(_.isEmpty(alleleCount.text)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_normal_ref_count_template"); return templateFn(vars); }, "normalAltCount": function(datum) { var mutation = datum.mutation; - var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.normalAltCount); + var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.get("normalAltCount")); var vars = {}; vars.normalAltCount = alleleCount.text; vars.normalAltCountClass = alleleCount.style; + // 508 compliance to prevent empty label tag + if(_.isEmpty(alleleCount.text)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_normal_alt_count_template"); return templateFn(vars); }, "tumorRefCount": function(datum) { var mutation = datum.mutation; - var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.tumorRefCount); + var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.get("tumorRefCount")); var vars = {}; vars.tumorRefCount = alleleCount.text; vars.tumorRefCountClass = alleleCount.style; + // 508 compliance to prevent empty label tag + if(_.isEmpty(alleleCount.text)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_tumor_ref_count_template"); return templateFn(vars); }, "tumorAltCount": function(datum) { var mutation = datum.mutation; - var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.tumorAltCount); + var alleleCount = MutationDetailsTableFormatter.getAlleleCount(mutation.get("tumorAltCount")); var vars = {}; vars.tumorAltCount = alleleCount.text; vars.tumorAltCountClass = alleleCount.style; + // 508 compliance to prevent empty label tag + if(_.isEmpty(alleleCount.text)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_tumor_alt_count_template"); return templateFn(vars); }, "startPos": function(datum) { var mutation = datum.mutation; - var startPos = MutationDetailsTableFormatter.getIntValue(mutation.startPos); - var vars = {}; - vars.startPos = startPos.text; - vars.startPosClass = startPos.style; - var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_start_pos_template"); - return templateFn(vars); + // check if data exists, + // if not we need to retrieve it from the data manager + if (_.isUndefined(mutation.get("startPos"))) + { + self.requestColumnData("variantAnnotation", "startPos"); + return MutationViewsUtil.renderTablePlaceHolder(); + } + else + { + var startPos = MutationDetailsTableFormatter.getIntValue(mutation.get("startPos")); + var vars = {}; + vars.startPos = startPos.text; + vars.startPosClass = startPos.style; + + // 508 compliance to prevent empty label tag + if(_.isEmpty(startPos.text)) { + return ""; + } + + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_start_pos_template"); + return templateFn(vars); + } }, "endPos": function(datum) { var mutation = datum.mutation; - var endPos = MutationDetailsTableFormatter.getIntValue(mutation.endPos); - var vars = {}; - vars.endPos = endPos.text; - vars.endPosClass = endPos.style; - var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_end_pos_template"); - return templateFn(vars); + // check if data exists, + // if not we need to retrieve it from the data manager + if (_.isUndefined(mutation.get("endPos"))) + { + self.requestColumnData("variantAnnotation", "endPos"); + return MutationViewsUtil.renderTablePlaceHolder(); + } + else + { + var endPos = MutationDetailsTableFormatter.getIntValue(mutation.get("endPos")); + var vars = {}; + vars.endPos = endPos.text; + vars.endPosClass = endPos.style; + + // 508 compliance to prevent empty label tag + if(_.isEmpty(endPos.text)) { + return ""; + } + + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_end_pos_template"); + return templateFn(vars); + } }, "sequencingCenter": function(datum) { var mutation = datum.mutation; - return mutation.sequencingCenter; + var value = mutation.get("sequencingCenter"); + if (value === undefined) { + return ""; + } + return value; }, "chr": function(datum) { var mutation = datum.mutation; - return mutation.chr; + + // check if data exists, + // if not we need to retrieve it from the data manager + if (_.isUndefined(mutation.get("chr"))) + { + self.requestColumnData("variantAnnotation", "chr"); + return MutationViewsUtil.renderTablePlaceHolder(); + } + else + { + return mutation.get("chr") || ""; + } }, "referenceAllele": function(datum) { var mutation = datum.mutation; - return mutation.referenceAllele; + + // check if data exists, + // if not we need to retrieve it from the data manager + if (_.isUndefined(mutation.get("referenceAllele"))) + { + self.requestColumnData("variantAnnotation", "referenceAllele"); + return MutationViewsUtil.renderTablePlaceHolder(); + } + else + { + return mutation.get("referenceAllele") || ""; + } }, "variantAllele": function(datum) { var mutation = datum.mutation; - return mutation.variantAllele; + + // check if data exists, + // if not we need to retrieve it from the data manager + if (_.isUndefined(mutation.get("variantAllele"))) + { + self.requestColumnData("variantAnnotation", "variantAllele"); + return MutationViewsUtil.renderTablePlaceHolder(); + } + else + { + return mutation.get("variantAllele") || ""; + } }, "igvLink": function(datum) { //vars.xVarLink = mutation.xVarLink; @@ -12670,23 +15117,27 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) "cBioPortal": function(datum) { var mutation = datum.mutation; - // portal value may be null, - // because we are retrieving the data through another ajax call... - if (datum.cBioPortal == null) + // check if cBioPortal data exists, + // if not we need to retrieve it from the data manager + if (_.isUndefined(mutation.get("cBioPortal"))) { + self.requestColumnData("cBioPortal"); // TODO make the image customizable? - var vars = {loaderImage: "images/ajax-loader.gif", width: 15, height: 15}; - var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_placeholder_template"); - return templateFn(vars); + return MutationViewsUtil.renderTablePlaceHolder(); } else { - var portal = MutationDetailsTableFormatter.getCbioPortal(datum.cBioPortal); + var portal = MutationDetailsTableFormatter.getCbioPortal(mutation.get("cBioPortal")); var vars = {}; vars.portalFrequency = portal.frequency; vars.portalClass = portal.style; + // 508 compliance to prevent empty label tag + if(_.isEmpty(portal.frequency)) { + return ""; + } + var templateFn = BackboneTemplateCache.getTemplateFn("mutation_table_cbio_portal_template"); return templateFn(vars); } @@ -12696,7 +15147,6 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) columnTooltips: { "simple": function(selector, helper) { var qTipOptions = MutationViewsUtil.defaultTableTooltipOpts(); - //$(selector).find('.simple-tip').qtip(qTipOptions); cbio.util.addTargetedQTip($(selector).find('.simple-tip'), qTipOptions); //tableSelector.find('.best_effect_transcript').qtip(qTipOptions); @@ -12720,8 +15170,8 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) qTipOptsCosmic.content = {text: "NA"}; // content is overwritten on render qTipOptsCosmic.events = {render: function(event, api) { - var model = {cosmic: mutation.cosmic, - keyword: mutation.keyword, + var model = {cosmic: mutation.get("cosmic"), + keyword: mutation.get("keyword"), geneSymbol: gene, total: $(label).text()}; @@ -12732,7 +15182,6 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) cosmicView.render(); }}; - //$(label).qtip(qTipOptsCosmic); cbio.util.addTargetedQTip(label, qTipOptsCosmic); }); }, @@ -12746,7 +15195,7 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) var mutationId = $(this).closest("tr.mutation-table-data-row").attr("id"); var mutation = mutationUtil.getMutationIdMap()[mutationId]; var fis = MutationDetailsTableFormatter.getFis( - mutation.functionalImpactScore, mutation.fisValue); + mutation.get("functionalImpactScore"), mutation.get("fisValue")); // copy default qTip options and modify "content" // to customize for predicted impact score @@ -12759,9 +15208,9 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) // need to update corresponding data sources properly var model = { impact: fis.value, - xvia: mutation.xVarLink.replace("getma.org", "mutationassessor.org/r2"), - msaLink: mutation.msaLink.replace("getma.org", "mutationassessor.org/r2"), - pdbLink: mutation.pdbLink.replace("getma.org", "mutationassessor.org/r2") + xvia: mutation.get("xVarLink").replace("getma.org", "mutationassessor.org/r2"), + msaLink: mutation.get("msaLink").replace("getma.org", "mutationassessor.org/r2"), + pdbLink: mutation.get("pdbLink").replace("getma.org", "mutationassessor.org/r2") }; var container = $(this).find('.qtip-content'); @@ -12771,7 +15220,6 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) fisTipView.render(); }}; - //$(this).qtip(qTipOptsOma); cbio.util.addTargetedQTip(this, qTipOptsOma); }); }, @@ -12779,16 +15227,15 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) var gene = helper.gene; var mutationUtil = helper.mutationUtil; var portalProxy = helper.dataProxies.portalProxy; - var additionalData= helper.additionalData; + var mutationTable = helper.table; var addTooltip = function (frequencies, cancerStudyMetaData, cancerStudyName) { $(selector).find('.mutation_table_cbio_portal').each(function(idx, ele) { var mutationId = $(this).closest("tr.mutation-table-data-row").attr("id"); var mutation = mutationUtil.getMutationIdMap()[mutationId]; - var cancerStudy = cancerStudyName || mutation.cancerStudy; + var cancerStudy = cancerStudyName || mutation.get("cancerStudy"); - //$(ele).qtip({ cbio.util.addTargetedQTip(ele, { content: {text: 'pancancer mutation bar chart is broken'}, events: { @@ -12797,9 +15244,9 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) cancerStudyMetaData: cancerStudyMetaData, cancerStudyName: cancerStudy, geneSymbol: gene, - keyword: mutation.keyword, - proteinPosStart: mutation.proteinPosStart, - mutationType: mutation.mutationType, + keyword: mutation.get("keyword"), + proteinPosStart: mutation.get("proteinPosStart"), + mutationType: mutation.get("mutationType"), qtipApi: api}; //var container = $(this).find('.qtip-content'); @@ -12817,12 +15264,12 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) }); }; - if (additionalData.pancanFrequencies != null) + if (mutationTable.getCustomData()["cBioPortal"] != null) { // TODO always get the cancerStudyName from the mutation data? portalProxy.getPortalData( {cancerStudyMetaData: true, cancerStudyName: true}, function(portalData) { - addTooltip(additionalData.pancanFrequencies, + addTooltip(mutationTable.getCustomData()["cBioPortal"], portalData.cancerStudyMetaData, portalData.cancerStudyName); }); @@ -12849,7 +15296,7 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) var mutationId = $(this).closest("tr.mutation-table-data-row").attr("id"); var mutation = mutationUtil.getMutationIdMap()[mutationId]; - var url = mutation.igvLink; + var url = mutation.get("igvLink"); // get parameters from the server and call related igv function $.getJSON(url, function(data) { @@ -12892,119 +15339,223 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) columnSort: { "mutationId": function(datum) { var mutation = datum.mutation; - return mutation.mutationId; + if (mutation.get("mutationId") === undefined) { + return ""; + } + return mutation.get("mutationId"); }, "mutationSid": function(datum) { var mutation = datum.mutation; - return mutation.mutationSid; + if (mutation.get("mutationSid") === undefined) { + return ""; + } + return mutation.get("mutationSid"); }, "caseId": function(datum) { var mutation = datum.mutation; - return mutation.caseId; + if (mutation.get("caseId") === undefined) { + return ""; + } + return mutation.get("caseId"); }, "proteinChange": function(datum) { - var proteinChange = datum.mutation.proteinChange; - var matched = proteinChange.match(/.*[A-Z]([0-9]+)[^0-9]+/); + var proteinChange = datum.mutation.get("proteinChange"); + //var matched = proteinChange.match(/.*[A-Z]([0-9]+)[^0-9]+/); + var alleleAndPosition = /[A-Za-z][0-9]+./g; + var position = /[0-9]+/g; + var nonNumerical = /[^0-9]+/g; + + var extractNonNumerical = function(matched) { + // this is to sort alphabetically + // in case the protein position values are the same + var buffer = matched[0].match(nonNumerical); + + if (buffer && buffer.length > 0) + { + var str = buffer.join(""); + buffer = []; + + // since we are returning a float value + // assigning numerical value for each character. + // we have at most 2 characters, so this should be safe... + for (var i=0; i 1) + // if match, then use the first integer value as sorting data + if (matched && matched.length > 0) { - return parseInt(matched[1]); + var toParse = matched[0]; + + // this is to sort alphabetically + if (buffer && buffer.length > 0) + { + // add the alphabetical information as the decimal part... + // (not the best way to ensure alphabetical sorting, + // but in this method we are only allowed to return a numerical value) + toParse += "." + buffer.join(""); + } + + return parseFloat(toParse); } else { + // no match at all: do not sort return -Infinity; } }, "cancerStudy": function(datum) { var mutation = datum.mutation; - return mutation.cancerStudy; + var value = mutation.get("cancerStudy"); + if (value === undefined) { + return ""; + } + return value; }, "tumorType": function(datum) { var mutation = datum.mutation; - return mutation.tumorType; + var value = mutation.get("tumorType"); + if (value === undefined) { + return ""; + } + return value; }, "mutationType": function(datum) { var mutation = datum.mutation; - return mutation.mutationType; + var value = mutation.get("mutationType"); + if (value === undefined) { + return ""; + } + return value; }, "cosmic": function(datum) { var mutation = datum.mutation; - return MutationDetailsTableFormatter.assignIntValue(mutation.cosmicCount); + return MutationDetailsTableFormatter.assignIntValue(mutation.getCosmicCount()); }, "cna": function(datum) { var mutation = datum.mutation; - return MutationDetailsTableFormatter.assignIntValue(mutation.cna); + return MutationDetailsTableFormatter.assignIntValue(mutation.get("cna")); }, "mutationCount": function(datum) { var mutation = datum.mutation; - return MutationDetailsTableFormatter.assignIntValue(mutation.mutationCount); + return MutationDetailsTableFormatter.assignIntValue(mutation.get("mutationCount")); }, "normalFreq": function(datum) { var mutation = datum.mutation; - return MutationDetailsTableFormatter.assignFloatValue(mutation.normalFreq); + return MutationDetailsTableFormatter.assignFloatValue(mutation.get("normalFreq")); }, "tumorFreq": function(datum) { var mutation = datum.mutation; - return MutationDetailsTableFormatter.assignFloatValue(mutation.tumorFreq); + return MutationDetailsTableFormatter.assignFloatValue(mutation.get("tumorFreq")); }, "mutationAssessor": function(datum) { var mutation = datum.mutation; return MutationDetailsTableFormatter.assignValueToPredictedImpact( - mutation.functionalImpactScore, - mutation.fisValue); + mutation.get("functionalImpactScore"), + mutation.get("fisValue")); }, "mutationStatus": function(datum) { var mutation = datum.mutation; - return mutation.mutationStatus; + var value = mutation.get("mutationStatus"); + if (value === undefined) { + return ""; + } + return value; }, "validationStatus": function(datum) { var mutation = datum.mutation; - return mutation.validationStatus; + var value = mutation.get("validationStatus"); + if (value === undefined) { + return ""; + } + return value; }, "normalRefCount": function(datum) { var mutation = datum.mutation; - return MutationDetailsTableFormatter.assignIntValue(mutation.normalRefCount); + return MutationDetailsTableFormatter.assignIntValue(mutation.get("normalRefCount")); }, "normalAltCount": function(datum) { var mutation = datum.mutation; - return MutationDetailsTableFormatter.assignIntValue(mutation.normalAltCount); + return MutationDetailsTableFormatter.assignIntValue(mutation.get("normalAltCount")); }, "tumorRefCount": function(datum) { var mutation = datum.mutation; - return MutationDetailsTableFormatter.assignIntValue(mutation.tumorRefCount); + return MutationDetailsTableFormatter.assignIntValue(mutation.get("tumorRefCount")); }, "tumorAltCount": function(datum) { var mutation = datum.mutation; - return MutationDetailsTableFormatter.assignIntValue(mutation.tumorAltCount); + return MutationDetailsTableFormatter.assignIntValue(mutation.get("tumorAltCount")); }, "startPos": function(datum) { var mutation = datum.mutation; - return MutationDetailsTableFormatter.assignIntValue(mutation.startPos); + return MutationDetailsTableFormatter.assignIntValue(mutation.get("startPos")); }, "endPos": function(datum) { var mutation = datum.mutation; - return MutationDetailsTableFormatter.assignIntValue(mutation.endPos); + return MutationDetailsTableFormatter.assignIntValue(mutation.get("endPos")); }, "sequencingCenter": function(datum) { var mutation = datum.mutation; - return mutation.sequencingCenter; + var value = mutation.get("sequencingCenter"); + if (value === undefined) { + value = ""; + } + return value; }, "chr": function(datum) { var mutation = datum.mutation; - return mutation.chr; + var value = mutation.get("chr"); + if (value === undefined) { + return ""; + } + return value; }, "referenceAllele": function(datum) { var mutation = datum.mutation; - return mutation.referenceAllele; + var value = mutation.get("referenceAllele"); + if (value === undefined) { + return ""; + } + return value; }, "variantAllele": function(datum) { var mutation = datum.mutation; - return mutation.variantAllele; + var value = mutation.get("variantAllele"); + if (value === undefined) { + return ""; + } + return value; }, "igvLink": function(datum) { var mutation = datum.mutation; - return mutation.igvLink; + var value = mutation.get("igvLink"); + if (value === undefined) { + return ""; + } + return value; }, "cBioPortal": function(datum) { var portal = datum.cBioPortal; @@ -13022,50 +15573,50 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) // the value returned by the render function. columnFilter: { "proteinChange": function(datum) { - return datum.mutation.proteinChange; + return datum.mutation.get("proteinChange") || ""; }, "mutationType": function(datum) { // use display value for mutation type, not the sort value var mutationType = MutationDetailsTableFormatter.getMutationType( - datum.mutation.mutationType); + datum.mutation.get("mutationType")); return mutationType.text; }, "cosmic": function(datum) { - return datum.mutation.cosmicCount; + return datum.mutation.getCosmicCount() || ""; }, "cna": function(datum) { - return datum.mutation.cna; + return datum.mutation.get("cna") || ""; }, "mutationCount": function(datum) { - return datum.mutation.mutationCount; + return datum.mutation.get("mutationCount") || ""; }, "normalFreq": function(datum) { - return datum.mutation.normalFreq; + return datum.mutation.get("normalFreq") || ""; }, "tumorFreq": function(datum) { - return datum.mutation.tumorFreq; + return datum.mutation.get("tumorFreq") || ""; }, "mutationAssessor": function(datum) { - return datum.mutation.functionalImpactScore; + return datum.mutation.get("functionalImpactScore") || ""; }, "normalRefCount": function(datum) { - return datum.mutation.normalRefCount; + return datum.mutation.get("normalRefCount") || ""; }, "normalAltCount": function(datum) { - return datum.mutation.normalAltCount; + return datum.mutation.get("normalAltCount") || ""; }, "tumorRefCount": function(datum) { - return datum.mutation.tumorRefCount; + return datum.mutation.get("tumorRefCount") || ""; }, "tumorAltCount": function(datum) { - return datum.mutation.tumorAltCount; + return datum.mutation.get("tumorAltCount") || ""; }, "startPos": function(datum) { - return datum.mutation.startPos; + return datum.mutation.get("startPos") || ""; }, "endPos": function(datum) { - return datum.mutation.endPos; + return datum.mutation.get("endPos") || ""; } }, // native "mData" function for DataTables plugin. if this is implemented, @@ -13077,54 +15628,6 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) // default config relies on columnRender, // columnSort, and columnFilter functions }, - // optional data retrieval functions for the additional data. - // these functions can be used to retrieve more data via ajax calls, - // to update the table on demand. - additionalData: { - "cBioPortal": function(helper) { - var pancanProxy = helper.dataProxies.pancanProxy; - var indexMap = helper.indexMap; - var dataTable = helper.dataTable; - var additionalData = helper.additionalData; - - // get the pancan data and update the data & display values - pancanProxy.getPancanData({cmd: "byProteinPos"}, mutationUtil, function(dataByPos) { - pancanProxy.getPancanData({cmd: "byHugos"}, mutationUtil, function(dataByGeneSymbol) { - var frequencies = PancanMutationDataUtil.getMutationFrequencies( - {protein_pos_start: dataByPos, hugo: dataByGeneSymbol}); - - additionalData.pancanFrequencies = frequencies; - - var tableData = dataTable.fnGetData(); - - // update mutation counts (cBioPortal data field) for each datum - _.each(tableData, function(ele, i) { - var proteinPosStart = ele[indexMap["datum"]].mutation.proteinPosStart; - - // update the value of the datum only if proteinPosStart value is valid - if (proteinPosStart > 0) - { - ele[indexMap["datum"]].cBioPortal = PancanMutationDataUtil.countByKey( - frequencies, proteinPosStart); - } - else - { - ele[indexMap["datum"]].cBioPortal = 0; - } - - // update but do not redraw, it is too slow - dataTable.fnUpdate(null, i, indexMap["cBioPortal"], false, false); - }); - - if (tableData.length > 0) - { - // this update is required to re-render the entire column! - dataTable.fnUpdate(null, 0, indexMap["cBioPortal"]); - } - }); - }); - } - }, // delay amount before applying the user entered filter query filteringDelay: 600, // WARNING: overwriting advanced DataTables options such as @@ -13169,7 +15672,8 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) var _selectedRow = null; - var _additionalData = {}; + // optional table specific data + var _customData = {}; /** * Generates the data table options for the given parameters. @@ -13244,7 +15748,7 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) self._addColumnTooltips({gene: gene, mutationUtil: mutationUtil, dataProxies: dataProxies, - additionalData: _additionalData}); + table: self}); self._addEventListeners(indexMap); var currSearch = oSettings.oPreviousSearch.sSearch; @@ -13284,8 +15788,8 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) // TODO mapping on mutationId and mutationSid... //var key = mutation.mutationId; //_rowMap[key] = nRow; - $(nRow).attr("id", mutation.mutationId); - $(nRow).addClass(mutation.mutationSid); + $(nRow).attr("id", mutation.get("mutationId")); + $(nRow).addClass(mutation.get("mutationSid")); $(nRow).addClass("mutation-table-data-row"); }, //"fnCreatedRow": function(nRow, aData, iDataIndex) { @@ -13301,17 +15805,24 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) //$(tableSelector).append(''); //$(tableSelector).find('thead tr').clone().appendTo($(tableSelector).find('tfoot')); -// // trigger corresponding event -// _dispatcher.trigger( -// MutationDetailsEvents.MUTATION_TABLE_READY); - - self._loadAdditionalData({ - gene: gene, - dataProxies: dataProxies, - indexMap: self.getIndexMap(), - additionalData: _additionalData, - dataTable: this + // set the data table instance as soon as the table is initialized + self.setDataTable(this); + + // 508 compliance: add a title to each of the checkboxes provided by + // the ColVis library. As the offending checkboxes don't become visible + // until the button is clicked, bind it to the click event + $(oSettings.nTableWrapper).find(".ColVis_MasterButton").one("click", function() { + jQuery.each($(".ColVis_radio"), function(key, value) { + // title is the first sibling's text + var title = $(value).siblings(':first').text(); + $(value).children(':first').attr('title', title); + }); }); + + // trigger corresponding event + _dispatcher.trigger( + MutationDetailsEvents.MUTATION_TABLE_INITIALIZED, + tableSelector); }, "fnHeaderCallback": function(nHead, aData, iStart, iEnd, aiDisplay) { $(nHead).find('th').addClass("mutation-details-table-header"); @@ -13487,43 +15998,134 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) var tip = _options.columns[colName].tip; var opts = {}; - // merge qTip options with the provided options object - if(_.isObject(tip)) - { - jQuery.extend(true, opts, qTipOptionsHeader, tip); - } - // if not an object, then assuming it is a string, - // just update the content - else + // if string, convert to an object + if(_.isString(tip)) { //$(this).attr("alt", tip); - qTipOptionsHeader.content = tip; - opts = qTipOptionsHeader; + tip = {content: tip}; } - //$(this).qtip(opts); - cbio.util.addTargetedQTip(this, opts); - } - }); + // merge qTip options with the provided options object + jQuery.extend(true, opts, qTipOptionsHeader, tip); + + //$(this).qtip(opts); + cbio.util.addTargetedQTip(this, opts); + } + }); + } + + /** + * Adds tooltips for the table footer cells. + * + * @param nFoot table footer + * @private + */ + function addFooterTooltips(nFoot) + { + var qTipOptions = MutationViewsUtil.defaultTableTooltipOpts(); + + var qTipOptionsFooter = {}; + jQuery.extend(true, qTipOptionsFooter, qTipOptions); + qTipOptionsFooter.position = {my:'top center', at:'bottom center', viewport: $(window)}; + + cbio.util.addTargetedQTip($(nFoot).find("th"), qTipOptionsFooter); + } + + // class instance to keep track of previous requests + var _requestHistory = {}; + + /** + * Requests column data from the data manager for the given data field name, + * and updates the corresponding column. + * + * @param dataFnName data function name for data manager request + * @param columnName name of the column to be updated/rendered + * @param callback [optional] callback to be invoked after data retrieval + */ + function requestColumnData(dataFnName, columnName, callback) + { + columnName = columnName || dataFnName; + + // do not request data at all for excluded columns, and + // only request once for the same dataFnName and columnName combination + if (self._visiblityMap[columnName] === "excluded" || + _requestHistory[dataFnName + ":" + columnName]) + { + return; + } + else + { + _requestHistory[dataFnName + ":" + columnName] = true; + } + + callback = callback || function(params, data) { + var mutationTable = params.mutationTable; + + // TODO is this the right place to store the custom table data? + if (data) + { + self.getCustomData()[dataFnName] = data; + } + + MutationViewsUtil.refreshTableColumn( + mutationTable.getDataTable(), + mutationTable.getIndexMap(), + columnName); + }; + + function getColumnData() + { + _dispatcher.off( + MutationDetailsEvents.MUTATION_TABLE_INITIALIZED, + getColumnData); + + // get the pdb data for the entire table + dataManager.getData(dataFnName, + {mutationTable: self}, + // TODO instead of a callback, + // listen to the data change/update events, and update the corresponding column? + callback + ); + } + + // if table is not initialized yet, wait for the init event + if (self.getDataTable() == null) + { + _dispatcher.on( + MutationDetailsEvents.MUTATION_TABLE_INITIALIZED, + getColumnData); + } + else + { + getColumnData(); + } + } + + function getMutations() + { + var mutations = null; + + if (mutationUtil) + { + mutations = mutationUtil.getMutations(); + } + + return mutations; } - /** - * Adds tooltips for the table footer cells. - * - * @param nFoot table footer - * @private - */ - function addFooterTooltips(nFoot) + function getCustomData() { - var qTipOptions = MutationViewsUtil.defaultTableTooltipOpts(); + return _customData; + } - var qTipOptionsFooter = {}; - jQuery.extend(true, qTipOptionsFooter, qTipOptions); - qTipOptionsFooter.position = {my:'top center', at:'bottom center', viewport: $(window)}; + function getMutationUtil() + { + return mutationUtil; + } - //tableSelector.find('tfoot th').qtip(qTipOptionsFooter); - //$(nFoot).find("th").qtip(qTipOptionsFooter); - cbio.util.addTargetedQTip($(nFoot).find("th"), qTipOptionsFooter); + function getGene() + { + return gene; } // override required functions @@ -13537,6 +16139,12 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies) this.setFilterEventActive = setFilterEventActive; this.getManualSearch = getManualSearch; this.cleanFilters = cleanFilters; + this.requestColumnData = requestColumnData; + this.getCustomData = getCustomData; + this.getMutations = getMutations; + this.getMutationUtil = getMutationUtil; + this.getGene = getGene; + //this.selectRow = selectRow; //this.getSelectedRow = getSelectedRow; this.dispatcher = this._dispatcher; @@ -13688,16 +16296,12 @@ MutationDiagram.prototype.defaultOpts = { lollipopTextAngle: 0, // rotation angle for the lollipop label // lollipopFillColor: "#B40000", lollipopFillColor: { // color of the lollipop data point - missense_mutation: "#008000", - nonsense_mutation: "#FF0000", - nonstop_mutation: "#FF0000", - frame_shift_del: "#FF0000", - frame_shift_ins: "#FF0000", - in_frame_ins: "#000000", - in_frame_del: "#000000", - splice_site: "#FF0000", - other: "#808080", // all other mutation types - default: "#800080" // default is used when there is a tie + missense: "#008000", + truncating: "#000000", + inframe: "#8B4513", + fusion: "#8B00C9", + other: "#8B00C9", // all other mutation types + default: "#BB0000" // default is used when there is a tie }, lollipopBorderColor: "#BABDB6", // border color of the lollipop data points lollipopBorderWidth: 0.5, // border width of the lollipop data points @@ -13729,6 +16333,7 @@ MutationDiagram.prototype.defaultOpts = { yAxisFont: "sans-serif", // font type of the y-axis labels yAxisFontSize: "10px", // font size of the y-axis labels yAxisFontColor: "#2E3436", // font color of the y-axis labels + yAxisAutoAdjust: true, // indicates whether to adjust max y-axis value after plot update animationDuration: 1000, // transition duration (in ms) used for highlight animations fadeDuration: 1500, // transition duration (in ms) used for fade animations /** @@ -13750,7 +16355,7 @@ MutationDiagram.prototype.defaultOpts = { position: {my:'bottom left', at:'top center',viewport: $(window)}}; //$(element).qtip(options); - cbio.util.addTargetedQTip(element, options, "mouseover"); + cbio.util.addTargetedQTip(element, options); }, /** * Default region tooltip function. @@ -13813,34 +16418,62 @@ MutationDiagram.prototype.updateOptions = function(options) self.options = jQuery.extend(true, {}, self.options, options); // recalculate global values - var xMax = self.xMax = self.calcXMax(self.options, self.data); - // TODO use current.pileup instead? - var maxCount = self.maxCount = self.calcMaxCount(self.data.pileups); - var yMax = self.yMax = self.calcYMax(self.options, maxCount); - - self.bounds = this.calcBounds(self.options); - self.xScale = this.xScaleFn(self.bounds, xMax); - self.yScale = this.yScaleFn(self.bounds, yMax); + self.updateGlobals(); }; /** * Rescales the y-axis by using the updated options and * latest (filtered) data. + * + * @param noUpdatePlot if set true, plot contents are NOT updated */ -MutationDiagram.prototype.rescaleYAxis = function() +MutationDiagram.prototype.rescaleYAxis = function(noUpdatePlot) { var self = this; - // TODO use current Pileup data (self.pileups) instead? - var maxCount = self.maxCount = self.calcMaxCount(self.data.pileups); - var yMax = self.calcYMax(self.options, maxCount); + // recalculate global values + self.updateGlobals(); // remove & draw y-axis self.svg.select(".mut-dia-y-axis").remove(); - self.drawYAxis(self.svg, self.yScale, yMax, self.options, self.bounds); + self.drawYAxis(self.svg, self.yScale, self.yMax, self.options, self.bounds); + + if (!noUpdatePlot) + { + // re-draw the plot with new scale + self.updatePlot(); + } +}; + + +/** + * Update global class fields such as bounds, scales, max, etc. + * wrt the given options. + * + * @param options diagram options + */ +MutationDiagram.prototype.updateGlobals = function(options) +{ + var self = this; + options = options || self.options; + + var pileups = self.data.pileups; // initial pileup data + + // in case auto adjust is enabled, + // use current pileup data instead of the initial pileup data + if (options.yAxisAutoAdjust) + { + pileups = self.pileups; + } + + var maxCount = self.maxCount = self.calcMaxCount(pileups); + + var xMax = self.xMax = self.calcXMax(options, self.data); + var yMax = self.yMax = self.calcYMax(options, maxCount); - // re-draw the plot with new scale - self.updatePlot(); + self.bounds = this.calcBounds(options); + self.xScale = this.xScaleFn(self.bounds, xMax); + self.yScale = this.yScaleFn(self.bounds, yMax); }; /** @@ -14313,7 +16946,7 @@ MutationDiagram.prototype.drawYAxis = function(svg, yScale, yMax, options, bound var formatter = function(value) { var formatted = ''; - if (value == yMax) + if (value === yMax) { formatted = value; @@ -14322,7 +16955,7 @@ MutationDiagram.prototype.drawYAxis = function(svg, yScale, yMax, options, bound formatted = ">" + value; } } - else if (value == 0) + else if (value === 0) { formatted = value; } @@ -14551,7 +17184,7 @@ MutationDiagram.prototype.updateColorMap = function(pileup, color) for (var i=0; i < pileup.mutations.length; i++) { // assign the same color to all mutations in this pileup - self.mutationColorMap[pileup.mutations[i].mutationId] = color; + self.mutationColorMap[pileup.mutations[i].get("mutationId")] = color; } }; @@ -14599,46 +17232,30 @@ MutationDiagram.prototype.getLollipopFillColor = function(options, pileup) if (_.isFunction(color)) { - value = color(); + value = color(pileup); } // check if the color is fixed - else if (typeof color === "string") + else if (_.isString(color)) { value = color; } - // assuming color is a map (an object) + // assuming color is an object else { - var types = PileupUtil.getMutationTypeArray(pileup); - - // check tie condition - if (types.length > 1 && - types[0].count == types[1].count) - { - var groups = PileupUtil.getMutationTypeGroups(pileup); + var mutationsByMainType = PileupUtil.groupMutationsByMainType(pileup); - // if all of the same group (for example: all truncating mutations) - if (groups.length == 1) - { - // color with the group color - // (assuming all types have the same color) - // TODO define group colors explicitly to be safer - value = color[types[0].type]; - } - // if not of the same group - else - { - // use default color - value = color.default; - } - } - else if (color[types[0].type] == undefined) + // no main type for the given mutations (this should not happen) + if (mutationsByMainType.length === 0) { - value = color.other; + // use default color + value = color.default; } + // color with the main type color else { - value = color[types[0].type]; + // mutationsByMainType array is sorted by mutation count, + // under tie condition certain types have priority over others + value = color[mutationsByMainType[0].type]; } } @@ -14973,6 +17590,13 @@ MutationDiagram.prototype.updatePlot = function(pileupData) // reset color mapping (for the new data we may have different pileup colors) self.mutationColorMap = {}; + if (self.options.yAxisAutoAdjust) + { + // rescale y-axis without updating the plot, + // otherwise... infinite recursion! + self.rescaleYAxis(true); + } + // re-draw plot area contents for new data self.drawPlot(self.svg, pileups, @@ -14982,16 +17606,16 @@ MutationDiagram.prototype.updatePlot = function(pileupData) self.yScale); // also re-add listeners - for (var selector in self.listeners) - { + //for (var selector in self.listeners) + _.each(_.keys(self.listeners), function(selector) { var target = self.svg.selectAll(selector); - for (var event in self.listeners[selector]) - { + //for (var event in self.listeners[selector]) + _.each(_.keys(self.listeners[selector]), function(event) { target.on(event, self.listeners[selector][event]); - } - } + }); + }); // reset highlight map self.highlighted = {}; @@ -15400,14 +18024,8 @@ MutationDiagram.prototype.fadeOut = function(element, callback) MutationDiagram.prototype.getSelectedElements = function() { var self = this; - var selected = []; - - for (var key in self.highlighted) - { - selected.push(self.highlighted[key]); - } - return selected; + return _.values(self.highlighted); }; /** @@ -15432,11 +18050,29 @@ MutationDiagram.prototype.isFiltered = function() return filtered; }; +MutationDiagram.prototype.getThreshold = function() +{ + return Math.max(this.maxCount, this.options.minLengthY); +}; + MutationDiagram.prototype.getMaxY = function() { return this.yMax; }; +MutationDiagram.prototype.getInitialMaxY = function() +{ + var self = this; + + if (!self.initialYMax) + { + var maxCount = self.calcMaxCount(self.data.pileups); + self.initialYMax = self.calcYMax(self.options, maxCount); + } + + return self.initialYMax; +}; + MutationDiagram.prototype.getMinY = function() { return this.options.minLengthY; @@ -16069,6 +18705,31 @@ function MutationPdbPanel(options, data, proxy, xScale) return svg; } + function xScaleFn(data) + { + var width = _options.elWidth - + (_options.marginLeft + _options.marginRight); + + var x = _options.marginLeft; + + return d3.scale.linear() + .domain([0, calcXMax(data)]) + .range([x, x + width]); + } + + function calcXMax(data) + { + var values = []; + + _.each(data, function(row) { + _.each(row, function(pdb) { + values.push(pdb.chain.mergedAlignment.uniprotTo); + }); + }); + + return _.max(values); + } + /** * Initializes the panel. */ @@ -16079,6 +18740,12 @@ function MutationPdbPanel(options, data, proxy, xScale) _rowData = PdbDataUtil.allocateChainRows(data); _maxExpansionLevel = calcMaxExpansionLevel(_rowData.length, _options.numRows); + // in case no xScale function provided, generate the scale by using the row data + if (xScale == null) + { + xScale = xScaleFn(_rowData); + } + // selecting using jQuery node to support both string and jQuery selector values var node = $(_options.el)[0]; var container = d3.select(node); @@ -16184,15 +18851,13 @@ function MutationPdbPanel(options, data, proxy, xScale) */ function reapplyListeners() { - for (var selector in _listeners) - { + _.each(_.keys(_listeners), function(selector) { var target = _svg.selectAll(selector); - for (var event in _listeners[selector]) - { + _.each(_.keys(_listeners[selector]), function(event) { target.on(event, _listeners[selector][event]); - } - } + }); + }); } /** @@ -17630,7 +20295,7 @@ function PancanMutationHistogram(byProteinPosData, byGeneData, cancer_study_meta qtip: qtip, overallCountText: function() {return countText({count:totalByKeyword}, {count:totalByGene}, totalSequenced);} }; -}; +} /* * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. @@ -17668,16 +20333,36 @@ function PancanMutationHistogram(byProteinPosData, byGeneData, cancer_study_meta * on the view wrt each event type. * * @param mainMutationView a MainMutationView instance - * @param mutationDiagram a MutationDiagram instance * * @author Selcuk Onur Sumer */ -function MainMutationController(mainMutationView, mutationDiagram) +function MainMutationController(mainMutationView) { + var _mutationDiagram = null; + function init() { - // add listeners to the custom event dispatcher of the diagram + if (mainMutationView.diagramView) + { + diagramInitHandler(mainMutationView.diagramView.mutationDiagram); + } + else + { + mainMutationView.dispatcher.on( + MutationDetailsEvents.DIAGRAM_INIT, + diagramInitHandler); + } + + // also init reset link call back + mainMutationView.addResetCallback(handleReset); + } + + function diagramInitHandler(mutationDiagram) + { + // update class variable + _mutationDiagram = mutationDiagram; + // add listeners to the custom event dispatcher of the diagram mutationDiagram.dispatcher.on( MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED, allDeselectHandler); @@ -17693,15 +20378,15 @@ function MainMutationController(mainMutationView, mutationDiagram) mutationDiagram.dispatcher.on( MutationDetailsEvents.DIAGRAM_PLOT_UPDATED, diagramUpdateHandler); - - // also init reset link call back - mainMutationView.addResetCallback(handleReset); } function handleReset(event) { // reset the diagram contents - mutationDiagram.resetPlot(); + if (_mutationDiagram) + { + _mutationDiagram.resetPlot(); + } // hide the filter info text mainMutationView.hideFilterInfo(); @@ -17709,7 +20394,8 @@ function MainMutationController(mainMutationView, mutationDiagram) function diagramUpdateHandler() { - if (mutationDiagram.isFiltered()) + if (_mutationDiagram && + _mutationDiagram.isFiltered()) { // display info text mainMutationView.showFilterInfo(); @@ -17724,7 +20410,8 @@ function MainMutationController(mainMutationView, mutationDiagram) function allDeselectHandler() { // hide filter reset info - if (!mutationDiagram.isFiltered()) + if (_mutationDiagram && + !_mutationDiagram.isFiltered()) { mainMutationView.hideFilterInfo(); } @@ -17734,7 +20421,8 @@ function MainMutationController(mainMutationView, mutationDiagram) { // check if all deselected // (always show text if still there is a selected data point) - if (mutationDiagram.getSelectedElements().length == 0) + if (_mutationDiagram && + _mutationDiagram.getSelectedElements().length == 0) { // hide filter reset info allDeselectHandler(); @@ -17789,24 +20477,24 @@ function MainMutationController(mainMutationView, mutationDiagram) * @param mainMutationView a MainMutationView instance * @param mut3dVisView a Mutation3dVisView instance * @param mut3dView a Mutation3dView instance - * @param mut3dVis singleton Mutation3dVis instance * @param pdbProxy proxy for pdb data * @param mutationUtil data utility class (having the related mutations) - * @param mutationDiagram a MutationDiagram instance - * @param mutationTable a MutationDetailsTable instance * @param geneSymbol hugo gene symbol (string value) * * @author Selcuk Onur Sumer */ function Mutation3dController(mutationDetailsView, mainMutationView, - mut3dVisView, mut3dView, mut3dVis, pdbProxy, mutationUtil, - mutationDiagram, mutationTable, geneSymbol) + mut3dVisView, mut3dView, pdbProxy, mutationUtil, geneSymbol) { // we cannot get pdb panel view as a constructor parameter, // since it is initialized after initializing this controller var _pdbPanelView = null; var _pdbTableView = null; + var _mut3dVisView = null; // a Mutation3dVisView instance + var _mut3dVis = null; // singleton Mutation3dVis instance + var _mutationDiagram = null; + // TODO this can be implemented in a better/safer way // ...find a way to bind the source info to the actual event @@ -17815,8 +20503,58 @@ function Mutation3dController(mutationDetailsView, mainMutationView, function init() { - // add listeners to the custom event dispatcher of the diagram + if (mainMutationView.diagramView) + { + diagramInitHandler(mainMutationView.diagramView.mutationDiagram); + } + else + { + mainMutationView.dispatcher.on( + MutationDetailsEvents.DIAGRAM_INIT, + diagramInitHandler); + } + + if (mainMutationView.tableView && + mainMutationView.tableView.mutationTable) + { + // add listeners for the mutation table view + mainMutationView.tableView.mutationTable.dispatcher.on( + MutationDetailsEvents.PDB_LINK_CLICKED, + pdbLinkHandler); + + mainMutationView.tableView.mutationTable.dispatcher.on( + MutationDetailsEvents.PROTEIN_CHANGE_LINK_CLICKED, + proteinChangeLinkHandler); + } + + // add listeners for the mutation 3d view + mut3dView.addInitCallback(mut3dInitHandler); + + // add listeners for the mutation details view + mutationDetailsView.dispatcher.on( + MutationDetailsEvents.GENE_TAB_SELECTED, + geneTabSelectHandler); + + // set mut3dVisView instance if it is already initialized + if (mut3dVisView) + { + vis3dCreateHandler(mut3dVisView) + } + // if not init yet, wait for the init event + else + { + mutationDetailsView.dispatcher.on( + MutationDetailsEvents.VIS_3D_PANEL_CREATED, + vis3dCreateHandler); + } + } + + function diagramInitHandler(mutationDiagram) + { + // update class variable + _mutationDiagram = mutationDiagram; + // add listeners to the custom event dispatcher of the diagram mutationDiagram.dispatcher.on( MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED, allDeselectHandler); @@ -17844,32 +20582,25 @@ function Mutation3dController(mutationDetailsView, mainMutationView, mutationDiagram.dispatcher.on( MutationDetailsEvents.DIAGRAM_PLOT_RESET, diagramResetHandler); + } - // add listeners for the mutation table view - mutationTable.dispatcher.on( - MutationDetailsEvents.PDB_LINK_CLICKED, - pdbLinkHandler); - - mutationTable.dispatcher.on( - MutationDetailsEvents.PROTEIN_CHANGE_LINK_CLICKED, - proteinChangeLinkHandler); - - // add listeners for the mutation 3d view - mut3dView.addInitCallback(mut3dInitHandler); - - // add listeners for the mutation 3d vis view - mut3dVisView.dispatcher.on( - MutationDetailsEvents.VIEW_3D_PANEL_CLOSED, - view3dPanelCloseHandler); + function vis3dCreateHandler(mutation3dVisView) + { + // init the 3d view initializer & 3D controller + if (mutation3dVisView) + { + _mut3dVisView = mutation3dVisView; + _mut3dVis = mutation3dVisView.options.mut3dVis; - mut3dVisView.dispatcher.on( - MutationDetailsEvents.VIEW_3D_STRUCTURE_RELOADED, - view3dReloadHandler); + // add listeners for the mutation 3d vis view + _mut3dVisView.dispatcher.on( + MutationDetailsEvents.VIEW_3D_PANEL_CLOSED, + view3dPanelCloseHandler); - // add listeners for the mutation details view - mutationDetailsView.dispatcher.on( - MutationDetailsEvents.GENE_TAB_SELECTED, - geneTabSelectHandler); + _mut3dVisView.dispatcher.on( + MutationDetailsEvents.VIEW_3D_STRUCTURE_RELOADED, + view3dReloadHandler); + } } function geneTabSelectHandler(gene) @@ -17892,10 +20623,10 @@ function Mutation3dController(mutationDetailsView, mainMutationView, // just hide the 3D view for now - if (mut3dVisView) + if (_mut3dVisView) { - mut3dVisView.resetPanelPosition(); - mut3dVisView.hideView(); + _mut3dVisView.resetPanelPosition(); + _mut3dVisView.hideView(); } } @@ -17913,10 +20644,10 @@ function Mutation3dController(mutationDetailsView, mainMutationView, { reset3dView(); - if (mut3dVisView != null) + if (_mut3dVisView != null) { - mut3dVisView.resetPanelPosition(); - mut3dVisView.maximizeView(); + _mut3dVisView.resetPanelPosition(); + _mut3dVisView.maximizeView(); } } @@ -17960,10 +20691,10 @@ function Mutation3dController(mutationDetailsView, mainMutationView, // update 3D view with the selected chain data var datum = element.datum(); - if (mut3dVisView != null) + if (_mut3dVisView != null) { - mut3dVisView.maximizeView(); - mut3dVisView.updateView(geneSymbol, datum.pdbId, datum.chain); + _mut3dVisView.maximizeView(); + _mut3dVisView.updateView(geneSymbol, datum.pdbId, datum.chain); } // also update the pdb table (highlight the corresponding row) @@ -17984,7 +20715,8 @@ function Mutation3dController(mutationDetailsView, mainMutationView, // highlight mutations on the 3D view // (highlight only if the corresponding view is visible) if (mut3dView.isVisible() && - mutationDiagram.isHighlighted()) + _mutationDiagram && + _mutationDiagram.isHighlighted()) { highlightSelected(); } @@ -18013,6 +20745,36 @@ function Mutation3dController(mutationDetailsView, mainMutationView, } } + function initPdbPanel(pdbColl) + { + // init pdb panel view if not initialized yet + if (_pdbPanelView == null) + { + _pdbPanelView = mainMutationView.initPdbPanelView(pdbColl); + + if (_pdbPanelView.pdbPanel) + { + // add listeners to the custom event dispatcher of the pdb panel + _pdbPanelView.pdbPanel.dispatcher.on( + MutationDetailsEvents.PANEL_CHAIN_SELECTED, + panelChainSelectHandler); + + _pdbPanelView.pdbPanel.dispatcher.on( + MutationDetailsEvents.PDB_PANEL_RESIZE_STARTED, + panelResizeStartHandler); + + _pdbPanelView.pdbPanel.dispatcher.on( + MutationDetailsEvents.PDB_PANEL_RESIZE_ENDED, + panelResizeEndHandler); + } + + // add listeners for the mutation 3d view + _pdbPanelView.addInitCallback(function(event) { + initPdbTable(pdbColl); + }); + } + } + function initPdbTable(pdbColl) { // init pdb table view if not initialized yet @@ -18070,35 +20832,36 @@ function Mutation3dController(mutationDetailsView, mainMutationView, } function diagramResetHandler() { - if (mut3dVisView && mut3dVisView.isVisible()) + if (_mut3dVisView && _mut3dVisView.isVisible()) { // reset all previous visualizer filters - mut3dVisView.refreshView(); + _mut3dVisView.refreshView(); } } function diagramUpdateHandler() { // refresh 3d view with filtered positions - if (mut3dVisView && mut3dVisView.isVisible()) + if (_mut3dVisView && _mut3dVisView.isVisible()) { - mut3dVisView.refreshView(); + _mut3dVisView.refreshView(); } } function allDeselectHandler() { - if (mut3dVisView && mut3dVisView.isVisible()) + if (_mut3dVisView && _mut3dVisView.isVisible()) { - mut3dVisView.resetHighlight(); - mut3dVisView.hideResidueWarning(); + _mut3dVisView.resetHighlight(); + _mut3dVisView.hideResidueWarning(); } } function diagramDeselectHandler(datum, index) { // check if the diagram is still highlighted - if (mutationDiagram.isHighlighted()) + if (_mutationDiagram && + _mutationDiagram.isHighlighted()) { // reselect with the reduced selection diagramSelectHandler(); @@ -18113,7 +20876,7 @@ function Mutation3dController(mutationDetailsView, mainMutationView, function diagramSelectHandler(datum, index) { // highlight the corresponding residue in 3D view - if (mut3dVisView && mut3dVisView.isVisible()) + if (_mut3dVisView && _mut3dVisView.isVisible()) { highlightSelected(); } @@ -18122,7 +20885,7 @@ function Mutation3dController(mutationDetailsView, mainMutationView, function diagramMouseoverHandler(datum, index) { // highlight the corresponding residue in 3D view - if (mut3dVisView && mut3dVisView.isVisible()) + if (_mut3dVisView && _mut3dVisView.isVisible()) { // selected pileups (mutations) on the diagram var pileups = getSelectedPileups(); @@ -18148,7 +20911,7 @@ function Mutation3dController(mutationDetailsView, mainMutationView, if (mutation) { // highlight the corresponding residue in 3D view - if (mut3dVisView && mut3dVisView.isVisible()) + if (_mut3dVisView && _mut3dVisView.isVisible()) { highlightSelected(); } @@ -18162,7 +20925,8 @@ function Mutation3dController(mutationDetailsView, mainMutationView, if (mutation) { // reset the view with the selected chain - reset3dView(mutation.pdbMatch.pdbId, mutation.pdbMatch.chainId); + reset3dView(mutation.get("pdbMatch").pdbId, + mutation.get("pdbMatch").chainId); } } @@ -18174,11 +20938,11 @@ function Mutation3dController(mutationDetailsView, mainMutationView, var mutationMap = mutationUtil.getMutationIdMap(); var mutation = mutationMap[mutationId]; - if (mutation) + if (mutation && _mutationDiagram) { // highlight the corresponding pileup (without filtering the table) - mutationDiagram.clearHighlights(); - mutationDiagram.highlightMutation(mutation.mutationSid); + _mutationDiagram.clearHighlights(); + _mutationDiagram.highlightMutation(mutation.get("mutationSid")); } return mutation; @@ -18194,10 +20958,13 @@ function Mutation3dController(mutationDetailsView, mainMutationView, { var pileups = []; - // get mutations for all selected elements - _.each(mutationDiagram.getSelectedElements(), function (ele, i) { - pileups = pileups.concat(ele.datum()); - }); + if (_mutationDiagram) + { + // get mutations for all selected elements + _.each(_mutationDiagram.getSelectedElements(), function (ele, i) { + pileups = pileups.concat(ele.datum()); + }); + } return pileups; } @@ -18224,7 +20991,7 @@ function Mutation3dController(mutationDetailsView, mainMutationView, function highlight3dResidues(pileupData, noWarning) { // highlight 3D residues for the initially selected diagram elements - var mappedCount = mut3dVisView.highlightView(pileupData, true); + var mappedCount = _mut3dVisView.highlightView(pileupData, true); var unmappedCount = pileupData.length - mappedCount; @@ -18237,11 +21004,11 @@ function Mutation3dController(mutationDetailsView, mainMutationView, // show a warning message if there is at least one unmapped selection if (unmappedCount > 0) { - mut3dVisView.showResidueWarning(unmappedCount, pileupData.length); + _mut3dVisView.showResidueWarning(unmappedCount, pileupData.length); } else { - mut3dVisView.hideResidueWarning(); + _mut3dVisView.hideResidueWarning(); } } @@ -18257,34 +21024,22 @@ function Mutation3dController(mutationDetailsView, mainMutationView, var gene = geneSymbol; var uniprotId = mut3dView.model.uniprotId; // TODO get this from somewhere else + // init (singleton) 3D panel if not initialized yet + if (!mutationDetailsView.is3dPanelInitialized()) + { + mutationDetailsView.init3dPanel(); + } + var initView = function(pdbColl) { // init pdb panel view if not initialized yet if (_pdbPanelView == null) { - _pdbPanelView = mainMutationView.initPdbPanelView(pdbColl); - - // add listeners to the custom event dispatcher of the pdb panel - _pdbPanelView.pdbPanel.dispatcher.on( - MutationDetailsEvents.PANEL_CHAIN_SELECTED, - panelChainSelectHandler); - - _pdbPanelView.pdbPanel.dispatcher.on( - MutationDetailsEvents.PDB_PANEL_RESIZE_STARTED, - panelResizeStartHandler); - - _pdbPanelView.pdbPanel.dispatcher.on( - MutationDetailsEvents.PDB_PANEL_RESIZE_ENDED, - panelResizeEndHandler); - - // add listeners for the mutation 3d view - _pdbPanelView.addInitCallback(function(event) { - initPdbTable(pdbColl); - }); + initPdbPanel(pdbColl); } // reload the visualizer content with the given pdb and chain - if (mut3dVisView != null && + if (_mut3dVisView != null && _pdbPanelView != null && pdbColl.length > 0) { @@ -18317,11 +21072,14 @@ function Mutation3dController(mutationDetailsView, mainMutationView, { // TODO this is not an ideal solution, but... // ...while we have multiple diagrams, the 3d visualizer is a singleton - var colorMapper = function(mutationId, pdbId, chain) { - return mutationDiagram.mutationColorMap[mutationId]; - }; + if (_mutationDiagram) + { + var colorMapper = function(mutationId, pdbId, chain) { + return _mutationDiagram.mutationColorMap[mutationId]; + }; - mut3dVis.updateOptions({mutationColorMapper: colorMapper}); + _mut3dVis.updateOptions({mutationColorMapper: colorMapper}); + } } init(); @@ -18363,8 +21121,11 @@ function Mutation3dController(mutationDetailsView, mainMutationView, * @author Selcuk Onur Sumer */ function MutationDetailsController( - mutationDetailsView, dataProxies, sampleArray, diagramOpts, tableOpts, mut3dVis) + mutationDetailsView, dataManager, dataProxies, options) { + var sampleArray = options.data.sampleList; + var viewOptions = options.view; + var renderOptions = options.render; var mutationProxy = dataProxies.mutationProxy; var pfamProxy = dataProxies.pfamProxy; var pdbProxy = dataProxies.pdbProxy; @@ -18384,47 +21145,80 @@ function MutationDetailsController( mutationDetailsView.dispatcher.on( MutationDetailsEvents.GENE_TABS_CREATED, geneTabCreateHandler); + + mutationDetailsView.dispatcher.on( + MutationDetailsEvents.VIS_3D_PANEL_INIT, + vis3dInitHandler); + } + + function vis3dInitHandler(container) + { + var vis3dOpts = viewOptions.vis3d; + + if (!vis3dOpts) + { + return; + } + + var basicOpts = { + appOptions: {el: container || "#mutation_details"} + }; + + var options = jQuery.extend(true, {}, basicOpts, vis3dOpts); + var mut3dVis = new Mutation3dVis("default3dView", options); + mut3dVis.init(); + init3dView(mut3dVis); } function geneTabSelectHandler(gene) { if (_geneTabView[gene] == null) { - initView(gene, sampleArray, diagramOpts, tableOpts); + initView(gene, sampleArray, viewOptions); } } function geneTabCreateHandler() { - // init 3D view if the visualizer is available + // initially hide 3d container + //init3dView(null); + mutationDetailsView.$el.find(".mutation-3d-container").hide(); + + // init the view for the first gene only + var genes = mutationProxy.getGeneList(); + initView(genes[0], sampleArray, viewOptions); + } + function init3dView(mut3dVis) + { var container3d = mutationDetailsView.$el.find(".mutation-3d-container"); + // init 3D view if the visualizer is available if (mut3dVis) { // TODO remove mutationProxy? - var mutation3dVisView = new Mutation3dVisView( - {el: container3d, - mut3dVis: mut3dVis, - pdbProxy: pdbProxy, - mutationProxy: mutationProxy}); + var mutation3dVisView = new Mutation3dVisView({ + el: container3d, + config: renderOptions.mutation3dVis, + mut3dVis: mut3dVis, + pdbProxy: pdbProxy, + mutationProxy: mutationProxy + }); mutation3dVisView.render(); // update reference to the 3d vis view _mut3dVisView = mutation3dVisView; + + mutationDetailsView.dispatcher.trigger( + MutationDetailsEvents.VIS_3D_PANEL_CREATED, + mutation3dVisView); } // if no visualizer, hide the 3D vis container else { $(container3d).hide(); } - - // init the view for the first gene only - - var genes = mutationProxy.getGeneList(); - - initView(genes[0], sampleArray, diagramOpts, tableOpts); } /** @@ -18432,20 +21226,14 @@ function MutationDetailsController( * * @param gene hugo gene symbol * @param cases array of case ids (samples) - * @param diagramOpts [optional] mutation diagram options - * @param tableOpts [optional] mutation table options + * @param viewOptions [optional] view options */ - function initView(gene, cases, diagramOpts, tableOpts) + function initView(gene, cases, viewOptions) { // callback function to init view after retrieving // sequence information. - var init = function(sequenceData, mutationData, pdbRowData) + var init = function(sequenceData, mutationData) { - // process data to add 3D match information - mutationData = processMutationData(mutationData, - mutationProxy.getMutationUtil(), - pdbRowData); - // TODO a new util for each instance instead? // var mutationUtil = new MutationDetailsUtil( // new MutationCollection(mutationData)); @@ -18455,49 +21243,36 @@ function MutationDetailsController( var model = {geneSymbol: gene, mutationData: mutationData, dataProxies: dataProxies, - sequence: sequenceData, - sampleArray: cases, - diagramOpts: diagramOpts, - tableOpts: tableOpts}; + dataManager: dataManager, + uniprotId: sequenceData.metadata.identifier, // TODO get uniprot id(s) from elsewhere + sampleArray: cases}; // init the main view var mainView = new MainMutationView({ el: "#mutation_details_" + cbio.util.safeProperty(gene), + config: renderOptions.mainMutation, model: model}); + mutationDetailsView.dispatcher.trigger( + MutationDetailsEvents.MAIN_VIEW_INIT, + mainView); + mainView.render(); - // update the reference after rendering the view + // update the references after rendering the view _geneTabView[gene].mainMutationView = mainView; + dataManager.addView(gene, mainView); - // TODO this can be implemented in a better way in the MainMutationView class - var components = mainView.initComponents(_mut3dVisView); - + // no mutation data, nothing to show... if (mutationData == null || mutationData.length == 0) { mainView.showNoDataInfo(); - components.tableView.hideView(); } - - // TODO init controllers in their corresponding view classes' init() method instead? - - // init controllers - new MainMutationController(mainView, components.diagram); - new MutationDetailsTableController( - components.tableView, components.diagram, mutationDetailsView); - - if (mut3dVis && - _mut3dVisView) + else { - new Mutation3dController(mutationDetailsView, mainView, - _mut3dVisView, components.view3d, mut3dVis, - pdbProxy, mutationUtil, - components.diagram, components.tableView.tableUtil, gene); + initComponents(mainView, gene, mutationUtil, sequenceData, viewOptions); } - - new MutationDiagramController( - components.diagram, components.tableView.tableUtil, mutationUtil); }; // get mutation data for the current gene @@ -18531,6 +21306,7 @@ function MutationDetailsController( servletParams.uniprotAcc = uniprotAcc; } + // TODO table can be initialized without the PFAM data... pfamProxy.getPfamData(servletParams, function(sequenceData) { // sequenceData may be null for unknown genes... if (sequenceData == null) @@ -18542,60 +21318,113 @@ function MutationDetailsController( // get the first sequence from the response var sequence = sequenceData[0]; - if (pdbProxy) - { - var uniprotId = sequence.metadata.identifier; - pdbProxy.getPdbRowData(uniprotId, function(pdbRowData) { - init(sequence, data, pdbRowData); - }); - } - else - { - init(sequence, data); - } + // get annotation data in any case + dataManager.getData("variantAnnotation", + {mutations: data}, + function(params, data) { + init(sequence, params.mutations); + }); }); }); } - /** - * Processes mutation data to add additional information. - * - * @param mutationData raw mutation data array - * @param mutationUtil mutation util - * @param pdbRowData pdb row data for the corresponding uniprot id - * @return {Array} mutation data array with additional attrs - */ - function processMutationData(mutationData, mutationUtil, pdbRowData) + function initComponents(mainView, gene, mutationUtil, sequenceData, viewOptions) { - if (!pdbRowData) + var diagramOpts = viewOptions.mutationDiagram; + var tableOpts = viewOptions.mutationTable; + var vis3dOpts = viewOptions.vis3d; + var infoPanelOpts = viewOptions.infoPanel; + var summaryOpts = viewOptions.mutationSummary; + + // init mutation table + var tableView = null; + + if (tableOpts) { - return mutationData; + tableView = mainView.initMutationTableView(tableOpts); + new MutationDetailsTableController(mainView, mutationDetailsView); } - var map = mutationUtil.getMutationIdMap(); + var summaryView = null; - _.each(mutationData, function(mutation, idx) { - if (mutation == null) + if (summaryOpts) + { + summaryView = mainView.initSummaryView(tableOpts); + } + + // init mutation diagram + var diagramView = null; + + function initDiagram() + { + if (diagramOpts) { - console.log('warning [processMutationData]: mutation (at index %d) is null.', idx); - return; + diagramView = mainView.initMutationDiagramView(diagramOpts, sequenceData); + + var mutationTable = null; + + if (tableView) + { + mutationTable = tableView.mutationTable; + } + + var infoView = null; + + // TODO info view can be initialized without depending on diagram view! + if (infoPanelOpts) + { + infoView = mainView.initMutationInfoView(infoPanelOpts); + new MutationInfoController(mainView); + } + + new MutationDiagramController( + diagramView.mutationDiagram, mutationTable, infoView, mutationUtil); } + } - // use model instance, since raw mutation data won't work with mutationToPdb - var mutationModel = map[mutation.mutationId]; - // find the matching pdb - var match = PdbDataUtil.mutationToPdb(mutationModel, pdbRowData); - // update the raw mutation object - mutation.pdbMatch = match; - // also update the corresponding MutationModel within the util - mutationModel.pdbMatch = match; - }); + if (mutationUtil.containsProteinChange(gene)) + { + initDiagram(); + } + // cannot initialize mutation diagram without protein change data + else + { + dataManager.getData("variantAnnotation", + //{mutationTable: tableView.mutationTable}, + {mutations: mainView.model.mutationData}, + function(params, data) { + initDiagram(); + }); - return mutationData; + // TODO diagram place holder? + } + + // init main mutation controller + new MainMutationController(mainView); + + if (vis3dOpts) + { + // just init the 3D button + var view3d = mainView.init3dView(null); + + new Mutation3dController(mutationDetailsView, mainView, + _mut3dVisView, view3d, pdbProxy, mutationUtil, gene); + } } init(); + + // public functions + this.getMainView = function(key) + { + return _geneTabView[key]; + }; + + this.get3dVisView = function() {return _mut3dVisView;}; + this.getMainViews = function() {return _geneTabView;}; + this.getDataManager = function() {return dataManager}; + this.getDataProxies = function() {return dataProxies}; } /* @@ -18641,12 +21470,17 @@ var MutationDetailsEvents = (function() var _allLollipopsDeselected = "mutationDiagramAllDeselected"; var _lollipopMouseover = "mutationDiagramLollipopMouseover"; var _lollipopMouseout = "mutationDiagramLollipopMouseout"; + var _mainViewInit = "mainMutationViewInit"; + var _diagramInit = "mutationDiagramInitialized"; var _diagramPlotUpdated = "mutationDiagramPlotUpdated"; var _diagramPlotReset = "mutationDiagramPlotReset"; var _mutationTableFiltered = "mutationTableFiltered"; + var _mutationTableInitialized = "mutationTableInitialized"; var _mutationTableRedrawn = "mutationTableRedrawn"; var _mutationTableHeaderCreated = "mutationTableHeaderCreated"; var _proteinChangeLinkClicked = "mutationTableProteinChangeLinkClicked"; + var _mutationTypeSelected = "infoPanelMutationTypeSelected"; + var _infoPanelInit = "infoPanelInit"; var _pdbLinkClicked = "mutationTablePdbLinkClicked"; var _pdbPanelResizeStarted = "mutationPdbPanelResizeStarted"; var _pdbPanelResizeEnded = "mutationPdbPanelResizeEnded"; @@ -18657,6 +21491,8 @@ var MutationDetailsEvents = (function() var _pdbTableReady = "mutationPdbTableReady"; var _geneTabSelected = "mutationDetailsGeneTabSelected"; var _geneTabsCreated = "mutationDetailsGeneTabsCreated"; + var _3dVisInit = "mutation3dPanelInit"; + var _3dVisCreated = "mutation3dPanelCreated"; var _3dPanelClosed = "mutation3dPanelClosed"; var _3dStructureReloaded = "mutation3dStructureReloaded"; @@ -18666,12 +21502,17 @@ var MutationDetailsEvents = (function() LOLLIPOP_MOUSEOVER: _lollipopMouseover, LOLLIPOP_MOUSEOUT: _lollipopMouseout, ALL_LOLLIPOPS_DESELECTED: _allLollipopsDeselected, + MAIN_VIEW_INIT: _mainViewInit, + DIAGRAM_INIT: _diagramInit, DIAGRAM_PLOT_UPDATED: _diagramPlotUpdated, DIAGRAM_PLOT_RESET: _diagramPlotReset, + MUTATION_TABLE_INITIALIZED: _mutationTableInitialized, MUTATION_TABLE_FILTERED: _mutationTableFiltered, MUTATION_TABLE_REDRAWN: _mutationTableRedrawn, MUTATION_TABLE_HEADER_CREATED: _mutationTableHeaderCreated, PROTEIN_CHANGE_LINK_CLICKED: _proteinChangeLinkClicked, + INFO_PANEL_MUTATION_TYPE_SELECTED: _mutationTypeSelected, + INFO_PANEL_INIT: _infoPanelInit, PDB_LINK_CLICKED: _pdbLinkClicked, PDB_PANEL_RESIZE_STARTED: _pdbPanelResizeStarted, PDB_PANEL_RESIZE_ENDED: _pdbPanelResizeEnded, @@ -18682,6 +21523,8 @@ var MutationDetailsEvents = (function() PDB_TABLE_READY: _pdbTableReady, GENE_TAB_SELECTED: _geneTabSelected, GENE_TABS_CREATED: _geneTabsCreated, + VIS_3D_PANEL_INIT: _3dVisInit, + VIS_3D_PANEL_CREATED: _3dVisCreated, VIEW_3D_STRUCTURE_RELOADED: _3dStructureReloaded, VIEW_3D_PANEL_CLOSED: _3dPanelClosed }; @@ -18722,18 +21565,51 @@ var MutationDetailsEvents = (function() * Listens to the various events and make necessary changes * on the view wrt each event type. * - * @param tableView a MutationDetailsTableView instance - * @param mutationDiagram a MutationDiagram instance + * @param mainMutationView a MainMutationView instance * @param mutationDetailsView a MutationDetailsView instance * * @author Selcuk Onur Sumer */ -function MutationDetailsTableController(tableView, mutationDiagram, mutationDetailsView) +function MutationDetailsTableController(mainMutationView, mutationDetailsView) { + var _mutationDiagram = null; + function init() { - // add listeners to the custom event dispatcher of the diagram + if (mainMutationView.diagramView) + { + diagramInitHandler(mainMutationView.diagramView.mutationDiagram); + } + else + { + mainMutationView.dispatcher.on( + MutationDetailsEvents.DIAGRAM_INIT, + diagramInitHandler); + } + + if (mainMutationView.infoView) + { + infoPanelInitHandler(mainMutationView.infoView); + } + else + { + mainMutationView.dispatcher.on( + MutationDetailsEvents.INFO_PANEL_INIT, + infoPanelInitHandler); + } + + // add listeners for the mutation details view + mutationDetailsView.dispatcher.on( + MutationDetailsEvents.GENE_TAB_SELECTED, + geneTabSelectHandler); + } + + function diagramInitHandler(mutationDiagram) + { + // update class variable + _mutationDiagram = mutationDiagram; + // add listeners to the custom event dispatcher of the diagram mutationDiagram.dispatcher.on( MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED, allDeselectHandler); @@ -18757,107 +21633,143 @@ function MutationDetailsTableController(tableView, mutationDiagram, mutationDeta mutationDiagram.dispatcher.on( MutationDetailsEvents.DIAGRAM_PLOT_RESET, diagramResetHandler); + } - // add listeners for the mutation details view - mutationDetailsView.dispatcher.on( - MutationDetailsEvents.GENE_TAB_SELECTED, - geneTabSelectHandler); + function infoPanelInitHandler(infoView) + { + // add listeners to the custom event dispatcher of the info panel view + if (infoView) + { + infoView.dispatcher.on( + MutationDetailsEvents.INFO_PANEL_MUTATION_TYPE_SELECTED, + infoPanelFilterHandler); + } } function diagramResetHandler() { - if (tableView) + if (mainMutationView.tableView) { // reset all previous table filters - tableView.resetFilters(); + mainMutationView.tableView.resetFilters(); } } function allDeselectHandler() { - if (tableView) + if (mainMutationView.tableView) { // remove all table highlights - tableView.clearHighlights(); + mainMutationView.tableView.clearHighlights(); - // roll back the table to its previous state - // (to the last state when a manual filtering applied) - tableView.rollBack(); + // filter with all visible diagram mutations + mainMutationView.tableView.filter(PileupUtil.getPileupMutations( + _mutationDiagram.pileups)); } } function deselectHandler(datum, index) { - if (tableView) + if (mainMutationView.tableView) { // remove all table highlights - tableView.clearHighlights(); + mainMutationView.tableView.clearHighlights(); var mutations = []; // get mutations for all selected elements - _.each(mutationDiagram.getSelectedElements(), function (ele, i) { - mutations = mutations.concat(ele.datum().mutations); - }); + if (_mutationDiagram) + { + _.each(_mutationDiagram.getSelectedElements(), function (ele, i) { + mutations = mutations.concat(ele.datum().mutations); + }); + } // reselect with the reduced selection if (mutations.length > 0) { // filter table for the selected mutations - tableView.filter(mutations); + mainMutationView.tableView.filter(mutations); } // rollback only if none selected else { - // roll back the table to its previous state - // (to the last state when a manual filtering applied) - tableView.rollBack(); + // filter with all visible diagram mutations + mainMutationView.tableView.filter(PileupUtil.getPileupMutations( + _mutationDiagram.pileups)); } } } function selectHandler(datum, index) { - if (tableView) + if (mainMutationView.tableView) { // remove all table highlights - tableView.clearHighlights(); + mainMutationView.tableView.clearHighlights(); var mutations = []; // get mutations for all selected elements - _.each(mutationDiagram.getSelectedElements(), function (ele, i) { - mutations = mutations.concat(ele.datum().mutations); - }); + if (_mutationDiagram) + { + _.each(_mutationDiagram.getSelectedElements(), function (ele, i) + { + mutations = mutations.concat(ele.datum().mutations); + }); + } // filter table for the selected mutations - tableView.filter(mutations); + mainMutationView.tableView.filter(mutations); + } + } + + function infoPanelFilterHandler(mutationType) + { + if (mainMutationView.tableView !== null) + { + // get currently filtered mutations + var mutations = mainMutationView.infoView.currentMapByType[mutationType]; + + if (_.size(mutations) > 0) + { + mainMutationView.tableView.filter(mutations); + } + // if all the mutations of this type are already filtered out, + // then show all mutations of this type + else + { + mutations = mainMutationView.infoView.initialMapByType[mutationType]; + mainMutationView.tableView.filter(mutations); + // clear search box value since the filtering with that value is no longer valid + mainMutationView.tableView.clearSearchBox(); + } } } function mouseoverHandler(datum, index) { - if (tableView) + if (mainMutationView.tableView) { // highlight mutations for the provided mutations - tableView.highlight(datum.mutations); + mainMutationView.tableView.highlight(datum.mutations); } } function mouseoutHandler(datum, index) { - if (tableView) + if (mainMutationView.tableView) { // remove all highlights - tableView.clearHighlights(); + mainMutationView.tableView.clearHighlights(); } } function geneTabSelectHandler(gene) { - if (tableView) + if (mainMutationView.tableView) { - var oTable = tableView.tableUtil.getDataTable(); + var oTable = mainMutationView.tableView.mutationTable.getDataTable(); // alternatively we can check if selected gene is this view's gene if (oTable.is(":visible")) @@ -18907,15 +21819,26 @@ function MutationDetailsTableController(tableView, mutationDiagram, mutationDeta * * @author Selcuk Onur Sumer */ -function MutationDiagramController(mutationDiagram, mutationTable, mutationUtil) +function MutationDiagramController(mutationDiagram, mutationTable, infoPanelView, mutationUtil) { function init() { // add listeners to the custom event dispatcher of the mutation table + if (mutationTable) + { + mutationTable.dispatcher.on( + MutationDetailsEvents.MUTATION_TABLE_FILTERED, + tableFilterHandler); + } - mutationTable.dispatcher.on( - MutationDetailsEvents.MUTATION_TABLE_FILTERED, - tableFilterHandler); + // TODO add info panel init handler, this will require controller parameter modification/simplification + // add listeners to the custom event dispatcher of the info panel view + if (infoPanelView) + { + infoPanelView.dispatcher.on( + MutationDetailsEvents.INFO_PANEL_MUTATION_TYPE_SELECTED, + infoPanelFilterHandler); + } // TODO make sure to call these event handlers before 3D controller's handler, // otherwise 3D update will not work properly. @@ -18969,6 +21892,29 @@ function MutationDiagramController(mutationDiagram, mutationTable, mutationUtil) } } + function infoPanelFilterHandler(mutationType) + { + if (mutationDiagram !== null) + { + // get currently filtered mutations + var mutations = infoPanelView.currentMapByType[mutationType]; + + if (_.size(mutations) > 0) + { + mutationDiagram.updatePlot(PileupUtil.convertToPileups( + new MutationCollection(mutations))); + } + // if all the mutations of this type are already filtered out, + // then show all mutations of this type + else + { + mutations = infoPanelView.initialMapByType[mutationType]; + mutationDiagram.updatePlot(PileupUtil.convertToPileups( + new MutationCollection(mutations))); + } + } + } + function proteinChangeLinkHandler(mutationId) { var mutationMap = mutationUtil.getMutationIdMap(); @@ -18978,13 +21924,155 @@ function MutationDiagramController(mutationDiagram, mutationTable, mutationUtil) { // highlight the corresponding pileup (without filtering the table) mutationDiagram.clearHighlights(); - mutationDiagram.highlightMutation(mutation.mutationSid); + mutationDiagram.highlightMutation(mutation.get("mutationSid")); + } + } + + init(); +} + +/* + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/** + * Controller class for the Mutation Diagram. + * Listens to the various events and make necessary changes + * on the view wrt each event type. + * + * @author Selcuk Onur Sumer + */ +function MutationInfoController(mainMutationView) +{ + var _mutationDiagram = null; + + function init() + { + // TODO if diagram is disabled, use table data instead... + + if (mainMutationView.diagramView) + { + diagramInitHandler(mainMutationView.diagramView.mutationDiagram); + } + else + { + mainMutationView.dispatcher.on( + MutationDetailsEvents.DIAGRAM_INIT, + diagramInitHandler); + } + } + + function diagramInitHandler(mutationDiagram) + { + // update class variable + _mutationDiagram = mutationDiagram; + + // add listeners to the custom event dispatcher of the diagram + mutationDiagram.dispatcher.on( + MutationDetailsEvents.DIAGRAM_PLOT_RESET, + diagramResetHandler); + + mutationDiagram.dispatcher.on( + MutationDetailsEvents.DIAGRAM_PLOT_UPDATED, + diagramUpdateHandler); + + mutationDiagram.dispatcher.on( + MutationDetailsEvents.LOLLIPOP_SELECTED, + selectHandler); + + mutationDiagram.dispatcher.on( + MutationDetailsEvents.LOLLIPOP_DESELECTED, + deselectHandler); + + mutationDiagram.dispatcher.on( + MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED, + allDeselectHandler); + } + + function allDeselectHandler() + { + diagramUpdateHandler(); + } + + function deselectHandler(datum, index) + { + if (mainMutationView.infoView) + { + var pileups = []; + + // get pileups for all selected elements + if (_mutationDiagram) + { + _.each(_mutationDiagram.getSelectedElements(), function (ele, i) { + pileups = pileups.concat(ele.datum()); + }); + } + + // reselect with the reduced selection + if (pileups.length > 0) + { + mainMutationView.infoView.updateView( + PileupUtil.getPileupMutations(pileups)); + } + // rollback only if none selected + else + { + // roll back the table to its previous state + // (to the last state when a manual filtering applied) + diagramUpdateHandler(); + } + } + } + + function selectHandler(datum, index) + { + deselectHandler(datum, index); + } + + function diagramResetHandler() + { + diagramUpdateHandler(); + } + + function diagramUpdateHandler() + { + if (mainMutationView.infoView) + { + mainMutationView.infoView.updateView( + PileupUtil.getPileupMutations(_mutationDiagram.pileups)); } } init(); } + /* * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. * @@ -19027,6 +22115,7 @@ function MutationMapper(options) { var self = this; var _mutationDetailsView = null; + var _mutationDetailsController = null; // default options object var _defaultOpts = { @@ -19041,10 +22130,23 @@ function MutationMapper(options) view: { mutationDiagram: {}, mutationTable: {}, + mutationSummary: {}, pdbPanel: {}, pdbTable: {}, + infoPanel: {}, vis3d: {} }, + // TODO make all backbone view classes customizable this way! + // this is mainly to override the default rendering behavior of backbone views + render: { + // MutationDetailsView options + mutationDetails: { + init: null, // function for custom init + format: null // function for custom format + }, + mainMutation: {}, + mutation3dVis: {} + }, // data proxy configuration // instance: custom instance, if provided all other parameters are ignored // instanceClass: constructor to initialize the data proxy @@ -19057,6 +22159,13 @@ function MutationMapper(options) data: {} } }, + variantAnnotationProxy: { + instance: null, + instanceClass: VariantAnnotationDataProxy, + options: { + data: {} + } + }, mutationProxy: { instance: null, instanceClass: MutationDataProxy, @@ -19066,6 +22175,13 @@ function MutationMapper(options) geneList: "" } }, + clinicalProxy: { + instance: null, + instanceClass: ClinicalDataProxy, + options: { + data: {} + } + }, pdbProxy: { instance: null, instanceClass: PdbDataProxy, @@ -19105,32 +22221,37 @@ function MutationMapper(options) data: {} } } + }, + // data manager configuration, + // dataFn: additional custom data retrieval functions + // dataProxies: additional data proxies + dataManager: { + dataFn: {}, + dataProxies: {} } }; // merge options with default options to use defaults for missing values var _options = jQuery.extend(true, {}, _defaultOpts, options); - function init(mut3dVis) + function init() { _options.proxy.mutationProxy.options.geneList = _options.data.geneList.join(" "); - // init all data proxies - var dataProxies = DataProxyUtil.initDataProxies( - _options.proxy, mut3dVis); + // init all data proxies & data manager + var dataProxies = DataProxyUtil.initDataProxies(_options.proxy); + _options.dataManager = jQuery.extend(true, {}, _options.dataManager, {dataProxies: dataProxies}); + var dataManager = new MutationDataManager(_options.dataManager); // TODO pass other view options (pdb table, pdb diagram, etc.) var model = { - mutationProxy: dataProxies.mutationProxy, - sampleArray: _options.data.sampleList, - tableOpts: _options.view.mutationTable, - diagramOpts: _options.view.mutationDiagram + mutationProxy: dataProxies.mutationProxy }; var viewOptions = {el: _options.el, - model: model, - mut3dVis: mut3dVis}; + config: _options.render.mutationDetails, + model: model}; var mutationDetailsView = new MutationDetailsView(viewOptions); _mutationDetailsView = mutationDetailsView; @@ -19138,11 +22259,11 @@ function MutationMapper(options) // init main controller... var controller = new MutationDetailsController( mutationDetailsView, + dataManager, dataProxies, - model.sampleArray, - model.diagramOpts, - model.tableOpts, - mut3dVis); + _options); + + _mutationDetailsController = controller; // ...and let the fun begin! mutationDetailsView.render(); @@ -19150,4 +22271,5 @@ function MutationMapper(options) this.init = init; this.getView = function() {return _mutationDetailsView;}; + this.getController = function() {return _mutationDetailsController;}; } diff --git a/build/mutationMapper.min.css b/build/mutationMapper.min.css index d48883f..20e832a 100644 --- a/build/mutationMapper.min.css +++ b/build/mutationMapper.min.css @@ -1 +1 @@ -.diagram-customize-close,.diagram-help-close,.mutation-3d-container,.mutation-3d-vis-help-close{float:right}.mutation-3d-initializer{padding-bottom:30px}.mutation-3d-container{width:430px;font-family:verdana,arial,sans-serif;font-size:12px;position:fixed;right:0;top:0;z-index:100;border-style:outset;border-color:#BABDB6;border-radius:15px;background-color:#FFF;padding:5px 10px 10px;-moz-border-radius:15px;-webkit-border-radius:15px;box-sizing:content-box}.mutation-3d-container .ui-resizable-w{width:16px;height:90%}.mutation-3d-container .ui-resizable-s{left:32px;height:16px;width:90%}.mutation-3d-container .ui-resizable-sw{height:32px;width:32px}.mutation-3d-vis-header{padding-bottom:5px}.mutation-3d-vis-container{position:relative;z-index:2;overflow:hidden}.mutation-3d-vis-loader{text-align:center}.mutation-3d-vis-help-init{text-align:right}.mutation-3d-vis-help-init table{width:100%}.mutation-3d-vis-help-content{width:386px;padding:5px;background-color:#eee;border:1px solid #d3d3d3}.mutation-3d-nomap-warning,.mutation-3d-residue-warning{text-align:center;color:red;font-weight:700}.mutation-3d-alpha-helix{font-weight:700;color:orange}.mutation-3d-beta-sheet{font-weight:700;color:#00F}.mutation-3d-loop{font-weight:700;color:#888}.mutation-3d-tied{color:purple;font-weight:700}.mutation-3d-highlighted{color:#FD0;font-weight:700}.mutation-3d-info{font-size:13px}.mutation-3d-controls-menu{margin-left:auto;margin-right:auto}.mutation-3d-info-title{border-bottom:1px solid #888;margin-bottom:5px}.mutation-3d-close,.mutation-3d-maximize,.mutation-3d-minimize{float:right;cursor:pointer;opacity:.6}.mutation-3d-button{padding-bottom:4px;padding-top:4px}.mutation-3d-buttons{padding-right:10px}.mutation-3d-chain-id,.mutation-3d-pdb-id{font-weight:700;font-style:italic}.mutation-3d-spin{margin-left:12px}.mutation-3d-zoom-label{text-align:right}.mutation-3d-zoom-slider{margin-left:2px;width:80px}.mutation-3d-protein-style-menu{border-right:1px solid #AAA}.mutation-3d-style-header{text-align:center;font-weight:700}.mutation-3d-vis img{width:24px;height:24px}.mutation-3d-mutation-style-menu input,.mutation-3d-protein-style-menu input{margin:0}.igv-link{cursor:pointer}.left-align-td{text-align:left}.missense_mutation{color:green;font-weight:700}.trunc_mutation{color:red;font-weight:700}.inframe_mutation{color:#000;font-weight:700}.other_mutation{color:grey;font-weight:700}.uniform_mutation{color:#8A2BE2;font-weight:700}.cna-hetloss,.cna-homdel{color:#00F;font-weight:700}.cna-hetloss{font-size:smaller}.cna-diploid{color:#000;font-size:xx-small}.cna-amp,.cna-gain{color:red;font-weight:700}.cna-gain{font-size:smaller}.cna-unknown{color:grey;font-size:xx-small}.mutation-details-tooltip{font-size:11px!important}.mutation-details-filter-info,.mutation-details-no-data-info{font-size:14px;color:red;font-family:verdana,arial,sans-serif}.mutation-details-filter-info{margin-bottom:10px}.mutation-details-no-data-info{margin-top:10px}.mutation-details-filter-reset{color:#1974B8!important;cursor:pointer}.mutation-details-tabs-ref{font-size:11px!important}.mutation-details-content{font-size:12px;min-width:480px}.mutation-3d-container h4,.mutation-details-content h4{margin-bottom:0;margin-top:0;color:#2153AA;font-family:verdana,arial,sans-serif;font-size:14px;font-weight:700;line-height:12px;text-align:justify}.mutation-3d-container a:link,.mutation-3d-container a:visited,.mutation-details-content a:link,.mutation-details-content a:visited{color:#1974b8;text-decoration:none}.ui-tabs-paging-next,.ui-tabs-paging-prev{background:0 0!important;border:none!important;line-height:95%}.ui-tabs-paging-next{padding-right:0!important}.ui-tabs-paging-disabled{display:none}.diagram-lollipop-tip,.diagram-region-tip{font-size:12px}.diagram-pfam-link{margin-right:10px}.diagram_toolbar{padding-top:10px;padding-left:10px}.mutation-diagram-customize,.mutation-diagram-help{margin-top:5px;padding:5px;background-color:#eee;border:1px solid #d3d3d3}.mutation-diagram-help{color:#222}.mutation-diagram-customize table{width:100%}.mutation-diagram-help li{font-size:80%!important}.mutation-diagram-help ul{padding-top:0}.diagram-customize{margin-left:25px}.diagram-y-axis-slider-area{width:230px}.diagram-y-axis-slider-area .diagram-slider-min-label{float:left;text-align:right;font-size:90%}.diagram-y-axis-slider-area .diagram-slider-max-label{float:right;text-align:left;font-size:90%}.diagram-y-axis-slider-area .diagram-slider-title{text-align:center;font-weight:700;margin-bottom:5px}.diagram-y-axis-limit-input{margin-left:8px}.mut-dia-data-point{cursor:pointer}.mutation-pdb-main-container{margin-bottom:10px}.mutation-pdb-main-container .mutation-pdb-panel-container{overflow:hidden;max-height:200px}.mutation-pdb-main-container .pdb-table-3d-icon{font-size:90%;font-weight:700}.mutation-pdb-main-container .pdb-table-3d-link{float:right}.pdb-chain-tip{font-size:12px}.pdb-chain-group{cursor:pointer}.pdb-chain-table-container .dataTables_filter{width:200px}.pdb-chain-table-container .dataTables_filter input{width:120px}.pdb-chain-table-container .dataTables_info{width:300px}.mutation-pdb-table-view .ColVis{float:left;padding-right:15%;margin-bottom:0}.mutation-pdb-main-container .pdb-chain-table{font-size:90%;color:#000}.mutation-pdb-main-container .pdb-chain-table td{font-size:100%}.mutation-pdb-main-container .pdb-chain-table-container{width:670px;padding-left:40px}.mutation-pdb-main-container .pdb-chain-table-loader{padding-left:40px}.mutation-pdb-main-container .pbd-chain-table-chain-cell label{font-weight:700;font-style:italic}.pdb-table-controls td{padding-left:45px}.pdb-table-controls .triangle{float:left;cursor:pointer}.mutation-pdb-table-header{font-weight:700!important}.mutation_pdb_datatable_filter{float:right;padding-top:3px}.mutation_pdb_datatable_info{float:left;padding-top:5px;font-size:90%}.oma_link{font-weight:700}.oma_high{color:#C83C3C;font-weight:700}.oma_medium{color:#9F6F47;font-weight:700}.oma_low{color:#988A3E;font-weight:700}.oma_neutral{color:#909090;font-weight:700}.mutation-assessor-link{margin-bottom:1px}.mutation-assessor-link .ma-msa-icon{background-color:#88C;color:#fff;padding-left:3px;padding-right:3px;font-size:80%}.mutation-assessor-link .ma-3d-icon{background-color:#88C;color:#fff;padding-left:6px;padding-right:6px;font-size:80%}.mutation-assessor-main-link img{padding-left:3px;padding-right:3px}.mutation-table-container .dataTables_filter{width:200px}.mutation-table-container .dataTables_filter input{width:120px}.mutation-table-container .dataTables_info{width:300px}.mutation-table-container .ColVis{float:left;padding-right:20%;margin-bottom:0}.mutation-table-container .unknown{background:#E0E0E0;color:#000;padding-left:5px;padding-right:5px}.mutation-table-container .mutation-table-protein-change{font-weight:700;font-style:italic;cursor:pointer}.mutation-table-container .mutation-table-3d-link{float:right}.mutation-table-container .mutation-table-igv-icon{background-color:#88C;color:#fff;padding-left:6px;padding-right:6px}.mutation-table-container .mutation-table-3d-icon{font-size:90%;font-weight:700}.mutation-table-container .best_effect_transcript{color:red}.mutation-table-container .mutation_details_table{font-size:90%;color:#000}.mutation-table-container .mutation_details_table td{font-size:100%}table.display tr.even.mutation-table-highlight td{background-color:#E9E900}table.display tr.odd.mutation-table-highlight td{background-color:#E0E000}.mutation-table-container{margin-bottom:40px}.mutation-details-table-header{font-weight:700!important}.cosmic-details-tip-info{padding-bottom:5px}.cosmic-details-table{font-size:11px!important}.mutation_datatables_filter{float:right;padding-top:3px}.mutation_datatables_download,.pancan_mutations_histogram_thumbnail{float:left}.mutation_datatables_info{float:left;padding-top:5px;font-size:90%}.mutation-table-container div.DTTT_container{margin-bottom:0} \ No newline at end of file +.diagram-customize-close,.diagram-help-close,.mutation-3d-container,.mutation-3d-vis-help-close{float:right}.mutation-3d-initializer{padding-bottom:30px}.mutation-3d-container{width:430px;font-family:verdana,arial,sans-serif;font-size:12px;position:fixed;right:0;top:0;z-index:100;border-style:outset;border-color:#BABDB6;border-radius:15px;background-color:#FFF;padding:5px 10px 10px;-moz-border-radius:15px;-webkit-border-radius:15px;box-sizing:content-box}.mutation-3d-container .ui-resizable-w{width:16px;height:90%}.mutation-3d-container .ui-resizable-s{left:32px;height:16px;width:90%}.mutation-3d-container .ui-resizable-sw{height:32px;width:32px}.mutation-3d-vis-header{padding-bottom:5px}.mutation-3d-vis-container{position:relative;z-index:2;overflow:hidden}.mutation-3d-vis-loader{text-align:center}.mutation-3d-vis-help-init{text-align:right}.mutation-3d-vis-help-init table{width:100%}.mutation-3d-vis-help-content{width:386px;padding:5px;background-color:#eee;border:1px solid #d3d3d3}.mutation-3d-nomap-warning,.mutation-3d-residue-warning{text-align:center;color:red;font-weight:700}.mutation-3d-alpha-helix{font-weight:700;color:orange}.mutation-3d-beta-sheet{font-weight:700;color:#00F}.mutation-3d-loop{font-weight:700;color:#888}.mutation-3d-highlighted{color:#FD0;font-weight:700}.mutation-3d-info{font-size:13px}.mutation-3d-controls-menu{margin-left:auto;margin-right:auto}.mutation-3d-info-title{border-bottom:1px solid #888;margin-bottom:5px}.mutation-3d-close,.mutation-3d-maximize,.mutation-3d-minimize{float:right;cursor:pointer;opacity:.6}.mutation-3d-button{padding-bottom:4px;padding-top:4px}.mutation-3d-buttons{padding-right:10px}.mutation-3d-chain-id,.mutation-3d-pdb-id{font-weight:700;font-style:italic}.mutation-3d-spin{margin-left:12px}.mutation-3d-zoom-label{text-align:right}.mutation-3d-zoom-slider{margin-left:2px;width:80px}.mutation-3d-protein-style-menu{border-right:1px solid #AAA}.mutation-3d-style-header{text-align:center;font-weight:700}.mutation-3d-vis img{width:24px;height:24px}.mutation-3d-mutation-style-menu input,.mutation-3d-protein-style-menu input{margin:0}.igv-link{cursor:pointer}.left-align-td{text-align:left}.missense_mutation{color:green;font-weight:700}.trunc_mutation{color:#000;font-weight:700}.inframe_mutation{color:#8B4513;font-weight:700}.other_mutation{color:#8B00C9;font-weight:700}.default_mutation{color:#B00;font-weight:700}.uniform_mutation{color:#8A2BE2;font-weight:700}.cna-hetloss,.cna-homdel{color:#00F;font-weight:700}.cna-hetloss{font-size:smaller}.cna-diploid{color:#000;font-size:xx-small}.cna-amp,.cna-gain{color:red;font-weight:700}.cna-gain{font-size:smaller}.cna-unknown{color:grey;font-size:xx-small}.mutation-details-tooltip{font-size:11px!important}.mutation-details-filter-info,.mutation-details-no-data-info{font-size:14px;color:red;font-family:verdana,arial,sans-serif}.mutation-details-filter-info{margin-bottom:10px}.mutation-details-no-data-info{margin-top:10px}.mutation-details-filter-reset{color:#1974B8!important;cursor:pointer}.mutation-details-tabs-ref{font-size:11px!important}.mutation-details-content{font-size:12px;min-width:480px}.mutation-3d-container h4,.mutation-details-content h4{margin-bottom:0;margin-top:0;color:#2153AA;font-family:verdana,arial,sans-serif;font-size:14px;font-weight:700;line-height:12px;text-align:justify}.mutation-3d-container a:link,.mutation-3d-container a:visited,.mutation-details-content a:link,.mutation-details-content a:visited{color:#1974b8;text-decoration:none}.ui-tabs-paging-next,.ui-tabs-paging-prev{background:0 0!important;border:none!important;line-height:95%}.ui-tabs-paging-next{padding-right:0!important}.ui-tabs-paging-disabled{display:none}.diagram-lollipop-tip,.diagram-region-tip{font-size:12px}.diagram-pfam-link{margin-right:10px}.diagram_toolbar{padding-top:10px;padding-left:10px}.mutation-diagram-customize,.mutation-diagram-help{margin-top:5px;padding:5px;background-color:#eee;border:1px solid #d3d3d3}.mutation-diagram-help{color:#222}.mutation-diagram-customize table{width:100%}.mutation-diagram-help li{font-size:80%!important}.mutation-diagram-help ul{padding-top:0}.diagram-customize{margin-left:25px}.diagram-y-axis-slider-area{width:230px}.diagram-y-axis-slider-area .diagram-slider-min-label{float:left;text-align:right;font-size:90%}.diagram-y-axis-slider-area .diagram-slider-max-label{float:right;text-align:left;font-size:90%}.diagram-y-axis-slider-area .diagram-slider-title{text-align:center;font-weight:700;margin-bottom:5px}.diagram-y-axis-limit-input{margin-left:8px}.mut-dia-data-point{cursor:pointer}.mutation-pdb-main-container{margin-bottom:10px}.mutation-pdb-main-container .mutation-pdb-panel-container{overflow:hidden;max-height:200px}.mutation-pdb-main-container .pdb-table-3d-icon{font-size:90%;font-weight:700}.mutation-pdb-main-container .pdb-table-3d-link{float:right}.pdb-chain-tip{font-size:12px}.pdb-chain-group{cursor:pointer}.pdb-chain-table-container .dataTables_filter{width:200px}.pdb-chain-table-container .dataTables_filter input{width:120px}.pdb-chain-table-container .dataTables_info{width:300px}.mutation-pdb-table-view .ColVis{float:left;padding-right:15%;margin-bottom:0}.mutation-pdb-main-container .pdb-chain-table{font-size:90%;color:#000}.mutation-pdb-main-container .pdb-chain-table td{font-size:100%}.mutation-pdb-main-container .pdb-chain-table-container{width:670px;padding-left:40px}.mutation-pdb-main-container .pdb-chain-table-loader{padding-left:40px}.mutation-pdb-main-container .pbd-chain-table-chain-cell label{font-weight:700;font-style:italic}.pdb-table-controls td{padding-left:45px}.pdb-table-controls .triangle{float:left;cursor:pointer}.mutation-pdb-table-header{font-weight:700!important}.mutation_pdb_datatable_filter{float:right;padding-top:3px}.mutation_pdb_datatable_info{float:left;padding-top:5px;font-size:90%}span.mutation-type-info{padding-right:10px;display:inline-block;line-height:2.5em}.mutation-type-info-link{cursor:pointer}div.mutation-info-panel-container{padding-bottom:10px}div.mutation-info-panel-content{padding-left:30px}span.mutation-type-count{padding:5px;color:#EFEFEF}span.missense_mutation_count{background-color:green;font-weight:700;border-radius:10px}span.trunc_mutation_count{background-color:#000;font-weight:700;border-radius:10px}span.inframe_mutation_count{background-color:#8B4513;font-weight:700;border-radius:10px}span.other_mutation_count{background-color:#8B00C9;font-weight:700;border-radius:10px}span.mutation-type-label{font-weight:400}.oma_link{font-weight:700}.oma_high{color:#C83C3C;font-weight:700}.oma_medium{color:#9F6F47;font-weight:700}.oma_low{color:#988A3E;font-weight:700}.oma_neutral{color:#909090;font-weight:700}.mutation-assessor-link{margin-bottom:1px}.mutation-assessor-link .ma-msa-icon{background-color:#88C;color:#fff;padding-left:3px;padding-right:3px;font-size:80%}.mutation-assessor-link .ma-3d-icon{background-color:#88C;color:#fff;padding-left:6px;padding-right:6px;font-size:80%}.mutation-assessor-main-link img{padding-left:3px;padding-right:3px}.mutation-table-container .dataTables_filter{width:200px}.mutation-table-container .dataTables_filter input{width:120px}.mutation-table-container .dataTables_info{width:300px}.mutation-table-container .ColVis{float:left;padding-right:20%;margin-bottom:0}.mutation-table-container .unknown{background:#E0E0E0;color:#000;padding-left:5px;padding-right:5px}.mutation-table-container .valid{background:#CFC;color:#000;padding-left:5px;padding-right:5px;font-weight:700}.mutation-table-container .somatic{background:#CFF;color:#000;padding-left:5px;padding-right:5px;font-weight:700}.mutation-table-container .germline{background:#FFC;color:#000;padding-left:3px;padding-right:3px;font-weight:700}.mutation-table-container .mutation-table-protein-change{font-weight:700;font-style:italic;cursor:pointer}.mutation-table-container .mutation-table-3d-link{float:right}.mutation-table-container .mutation-table-igv-icon{background-color:#88C;color:#fff;padding-left:6px;padding-right:6px}.mutation-table-container .mutation-table-3d-icon{font-size:90%;font-weight:700}.mutation-table-container .best_effect_transcript{color:red}.mutation-table-container .mutation_details_table{font-size:90%;color:#000}.mutation-table-container .mutation_details_table td{font-size:100%}table.display tr.even.mutation-table-highlight td{background-color:#E9E900}table.display tr.odd.mutation-table-highlight td{background-color:#E0E000}.mutation-table-container{margin-bottom:40px}.mutation-details-table-header{font-weight:700!important}.cosmic-details-tip-info{padding-bottom:5px}.cosmic-details-table{font-size:11px!important}.mutation_datatables_filter{float:right;padding-top:3px}.mutation_datatables_download,.pancan_mutations_histogram_thumbnail{float:left}.mutation_datatables_info{float:left;padding-top:5px;font-size:90%}.mutation-table-container div.DTTT_container{margin-bottom:0} \ No newline at end of file diff --git a/build/mutationMapper.min.js b/build/mutationMapper.min.js index 8ce0c5a..415e00a 100644 --- a/build/mutationMapper.min.js +++ b/build/mutationMapper.min.js @@ -1,5 +1,6 @@ -function JSmolWrapper(){function t(t,e,n){a=t,o=jQuery.extend(!0,{},h,e);var i=o.width,m=4*o.height;r='';var f=function(t){if(cbio.util.getWindowOrigin()==t.origin)if("ready"==t.data.type)l&&(u=cbio.util.getTargetDocument("jsmol_frame"));else if("menu"==t.data.type)s&&("visible"==t.data.content?s.css("overflow","visible"):"hidden"==t.data.content&&s.css("overflow","hidden"));else if("done"==t.data.type){var e=p[t.data.scriptId];if(null!=e){delete p[t.data.scriptId];var n=e.callback;n&&_.isFunction(n)&&n()}_.isEmpty(d)||(e=d.shift(),p[e.data.scriptId]=e,l.postMessage(e.data,c))}};window.addEventListener("message",f,!1)}function e(t){t&&r&&(t.empty(),t.append(r),s=t),l=cbio.util.getTargetWindow("jsmol_frame"),l||console.log("warning: JSmol frame cannot be initialized properly")}function n(t,e){if(l){m=(m+1)%1e6;var n={type:"script",content:t,scriptId:"script_"+m};i(n,e)}}function i(t,e){var n={data:t,callback:e};_.isEmpty(d)?(p[n.data.scriptId]=n,l.postMessage(t,c)):d.push(n)}var a=null,o=null,r=null,l=null,u=null,s=null,c=cbio.util.getWindowOrigin(),d=[],p={},m=0,h={use:"HTML5",j2sPath:"js/lib/jsmol/j2s",disableJ2SLoadMonitor:!0,disableInitialConsole:!0};return{init:t,updateContainer:e,script:n}}function JmolScriptGenerator(){function t(t){return"load="+t+";"}function e(){return"select all;"}function n(){return"select none;"}function i(t){return S[t]}function a(t){return"color ["+P(t)+"];"}function o(t){return"select :"+t+";"}function r(t){return"select :"+t+" and helix;"}function l(t){return"select :"+t+" and sheet;"}function u(t){var e="@{{:"+t+"}.atomNo.min}",n="@{{:"+t+"}.atomNo.max}";return'color atoms property atomNo "roygb" range '+e+" "+n+";"}function s(t){return"color atoms CPK;"}function c(){return"restrict protein;"}function d(t){return t>0?"color translucent;":"color opaque;"}function p(t){var e=function(t){var e="";return null!=t&&t.length>0&&(e+="^"+t),e},n=t.start.pdbPos+e(t.start.insertion);return t.end.pdbPos>t.start.pdbPos&&(n+="-"+t.end.pdbPos+e(t.end.insertion)),n}function m(t,e){return"select ("+t.join(", ")+") and :"+e+";"}function h(t,e){return"select (("+t.join(", ")+") and :"+e+" and sidechain) or (("+t.join(", ")+") and :"+e+" and *.CA);"}function f(){return"wireframe 0.15; spacefill 25%;"}function g(){return"wireframe OFF; spacefill OFF;"}function v(t,e){var n=this,i=n.scriptPosition(t);return"center "+i+":"+e+";"}function b(){return"center;"}function y(){return"zoom in;"}function _(){return"zoom out;"}function T(t){return"spin "+t+";"}function C(t,e,n,i){var a=this,o=[];o.push(a.selectPositions(t,i.chainId)),o.push(a.setColor(e));var r="none"!=n.displaySideChain;return o=o.concat(a.generateSideChainScript(t,r,n,i))}function P(t){return t.replace("#","x")}var S={ballAndStick:"wireframe ONLY; wireframe 0.15; spacefill 20%;",spaceFilling:"spacefill ONLY; spacefill 100%;",ribbon:"ribbon ONLY;",cartoon:"cartoon ONLY;",trace:"trace ONLY;"};this.loadPdb=t,this.selectAll=e,this.selectNone=n,this.setScheme=i,this.setColor=a,this.selectChain=o,this.selectAlphaHelix=r,this.selectBetaSheet=l,this.rainbowColor=u,this.cpkColor=s,this.hideBoundMolecules=c,this.setTransparency=d,this.scriptPosition=p,this.selectPositions=m,this.selectSideChains=h,this.enableBallAndStick=f,this.disableBallAndStick=g,this.highlightScript=C,this.center=v,this.defaultZoomIn=y,this.defaultZoomOut=_,this.defaultCenter=b,this.spin=T}function JmolWrapper(t){function e(t,e){u=jQuery.extend(!0,{},l,e),delete Jmol._tracker,o=Jmol.getApplet(t,u),r=$("#"+t+"_appletinfotablediv"),r.hide()}function n(t){null!=r&&(t.append(r),r.show())}function i(t,e){Jmol.script(o,t),_.isFunction(e)&&e()}function a(t){return t?{jarPath:"js/lib/jmol/",jarFile:"JmolAppletSigned.jar",disableJ2SLoadMonitor:!0,disableInitialConsole:!0}:{use:"HTML5",j2sPath:"js/lib/jsmol/j2s",disableJ2SLoadMonitor:!0,disableInitialConsole:!0}}var o=null,r=null,l=a(t),u=null;return{init:e,updateContainer:n,script:i}}function MergedAlignmentSegmentor(t){function e(){return o=a;a++)e.push(a);return t.start.insertion&&(e[0]+="^"+t.start.insertion),e.length>1&&t.end.insertion&&(e[e.length-1]+="^"+t.end.insertion),e}function u(t,e){return P={rescode:t,chain:e},""}function s(t,e){return P={rescode:t,chain:e},""}function c(t,e,n,i){var a=this,o=[""];a.selectPositions(t,i.chainId),a.setColor(e);var r="none"!=n.displaySideChain;return a.generateSideChainScript(t,r,n,i),o}function d(){var t=_.extend({},S,D.ballAndStick);return t.sphere.color=w,t.stick.color=w,C.setStyle(P,t),""}function p(){return""}function m(t){return P={chain:t},i("spectrum"),""}function h(t){return P={chain:t},_.each(S,function(t){delete t.color,t.colors=$3Dmol.elementColors.defaultColors}),C.setStyle(P,S),""}function f(t){return t.replace("#","0x")}function g(t){C=t}function v(t){T=t}function b(){var t={resn:["asp","glu","arg","lys","his","asn","thr","cys","gln","tyr","ser","gly","ala","leu","val","ile","met","trp","phe","pro","ASP","GLU","ARG","LYS","HIS","ASN","THR","CYS","GLN","TYR","SER","GLY","ALA","LEU","VAL","ILE","MET","TRP","PHE","PRO"],invert:!0},e={sphere:{hidden:!0}};C.setStyle(t,e)}function y(t){_.each(S,function(e){e.opacity=(10-t)/10}),C.setStyle(P,S)}var T=null,C=null,P=null,S=null,w=null,D={ballAndStick:{stick:{},sphere:{scale:.25}},spaceFilling:{sphere:{scale:.6}},cartoon:{cartoon:{}},ribbon:{cartoon:{style:"ribbon"}},trace:{cartoon:{style:"trace"}}};this.setViewer=g,this.setPdbUri=v,this.loadPdb=t,this.selectAll=e,this.setScheme=n,this.setColor=i,this.selectChain=a,this.selectAlphaHelix=o,this.selectBetaSheet=r,this.scriptPosition=l,this.selectPositions=u,this.selectSideChains=s,this.highlightScript=c,this.rainbowColor=m,this.cpkColor=h,this.enableBallAndStick=d,this.disableBallAndStick=p,this.hideBoundMolecules=b,this.setTransparency=y}function Mol3DWrapper(){function t(t,e){o=jQuery.extend(!0,{},a,e),$(e.el).append("
");var n=$("#"+t);n.hide();var i=$3Dmol.createViewer(n,{defaultcolors:$3Dmol.elementColors.rasmol});i.setBackgroundColor(16777215),r=i}function e(t){null!=r&&r.setContainer(t)}function n(t,e){null!=t&&null!=r&&r.render(),_.isFunction(e)&&e()}function i(){return r}var a={},o=null,r=null;return{init:t,updateContainer:e,getViewer:i,script:n}}function MolScriptGenerator(){this.loadPdb=function(t){return""},this.selectAll=function(){return""},this.selectNone=function(){return""},this.setScheme=function(t){return""},this.setColor=function(t){return""},this.selectChain=function(t){return""},this.selectAlphaHelix=function(t){return""},this.selectBetaSheet=function(t){return""},this.rainbowColor=function(t){return""},this.cpkColor=function(t){return""},this.hideBoundMolecules=function(){return""},this.setTransparency=function(t){return""},this.scriptPosition=function(t){return""},this.selectPositions=function(t,e){return""},this.selectSideChains=function(t,e){return""},this.enableBallAndStick=function(){return""},this.disableBallAndStick=function(){return""},this.center=function(t,e){return""},this.zoom=function(t){return""},this.defaultZoomIn=function(){return""},this.defaultZoomOut=function(){return""},this.defaultCenter=function(){return""},this.spin=function(t){return""},this.highlightScript=function(t,e,n,i){return[]},this.generateVisualStyleScript=function(t,e,n){var i=this,a=[];a.push(i.selectAll()),a.push(i.setScheme(n.proteinScheme)),a.push(i.setColor(n.defaultColor)),a.push(i.setTransparency(n.defaultTranslucency)),a.push(i.selectChain(e.chainId)),a.push(i.setColor(n.chainColor)),a.push(i.setTransparency(n.chainTranslucency)),a.push(i.selectChain(e.chainId)),"byAtomType"==n.colorProteins?a.push(i.cpkColor(e.chainId)):"bySecondaryStructure"==n.colorProteins?(a.push(i.selectAlphaHelix(e.chainId)),a.push(i.setColor(n.structureColors.alphaHelix)),a.push(i.selectBetaSheet(e.chainId)),a.push(i.setColor(n.structureColors.betaSheet))):"byChain"==n.colorProteins&&(a.push(i.selectChain(e.chainId)),a.push(i.rainbowColor(e.chainId)));for(var o in t)a.push(i.selectPositions(t[o],e.chainId)),"byMutationType"==n.colorMutations?a.push(i.setColor(o)):"uniform"==n.colorMutations&&a.push(i.setColor(n.mutationColor)),a=a.concat(i.generateSideChainScript(t[o],"all"==n.displaySideChain,n,e));return n.restrictProtein&&a.push(i.hideBoundMolecules()),a},this.generateSideChainScript=function(t,e,n,i){var a=this,o=[];return"spaceFilling"!=n.proteinScheme&&(o.push(a.selectSideChains(t,i.chainId)),e?o.push(a.enableBallAndStick()):o.push(a.disableBallAndStick())),o},this.generateHighlightScript=function(t,e,n,i){var a=this,o=[];if(!_.isEmpty(t)){var r=a.highlightScriptPositions(t);o=o.concat(a.highlightScript(r,e,n,i))}return o},this.highlightScriptPositions=function(t){var e=this,n=[];return _.each(t,function(t){n.push(e.scriptPosition(t))}),n}}function MutationInputParser(){function t(){return{proteinPosEnd:"",uniprotId:"",cancerType:"",tumorType:"",cancerStudyLink:"",codonChange:"",proteinPosStart:"",linkToPatientView:"",geneticProfileId:"",mutationCount:"",mutationType:"",referenceAllele:"",uniprotAcc:"",fisValue:"",functionalImpactScore:"",cancerStudy:"",normalRefCount:"",ncbiBuildNo:"",normalFreq:"",cancerStudyShort:"",msaLink:"",mutationStatus:"",cna:"",proteinChange:"",aminoAcidChange:"",endPos:"",refseqMrnaId:"",geneSymbol:"",tumorFreq:"",startPos:"",keyword:"",cosmic:"",validationStatus:"",mutationSid:"",normalAltCount:"",variantAllele:"",mutationId:"",caseId:"",xVarLink:"",pdbLink:"",tumorAltCount:"",tumorRefCount:"",sequencingCenter:"",chr:""}}function e(t){var e=[],i=t.split("\n");if(i.length>0)for(var o=a(i[0]),r=1;r0&&e.push(n(i[r],o));return u=e,e}function n(e,n){var a=t(),o=e.split(" ");return _.each(_.keys(a),function(t){a[t]=i(t,o,n)}),a.mutationId=a.mutationId||l(),a.mutationSid=a.mutationSid||a.mutationId,a}function i(t,e,n){var i=p[t],a=n[i],o="";return null!=a&&(o=e[a]||""),o}function a(t){var e=t.split(" "),n={};return _.each(e,function(t,e){n[t.toLowerCase()]=e}),n}function o(){if(null==u)return[];if(null==c){var t={};_.each(u,function(e,n){null!=e.caseId&&e.caseId.length>0&&(t[e.caseId]=e.caseId)}),c=_.values(t)}return c}function r(){if(null==u)return[];if(null==s){var t={};_.each(u,function(e,n){null!=e.geneSymbol&&e.geneSymbol.length>0&&(t[e.geneSymbol.toUpperCase()]=e.geneSymbol.toUpperCase())}),s=_.values(t)}return s}function l(){return d++,"stalone_mut_"+d}var u=null,s=null,c=null,d=0,p={proteinPosEnd:"protein_position_end",uniprotId:"uniprot_id",cancerType:"cancer_type",tumorType:"tumor_type",cancerStudyLink:"cancer_study_link",codonChange:"codon_change",proteinPosStart:"protein_position_start",linkToPatientView:"patient_view_link",geneticProfileId:"genetic_profile_id",mutationCount:"mutation_count",mutationType:"mutation_type",referenceAllele:"reference_allele",uniprotAcc:"uniprot_accession",fisValue:"fis_value",functionalImpactScore:"fis",cancerStudy:"cancer_study",normalRefCount:"normal_ref_count",ncbiBuildNo:"ncbi_build",normalFreq:"normal_frequency",cancerStudyShort:"cancer_study_short",msaLink:"msa_link",mutationStatus:"mutation_status",cna:"copy_number",proteinChange:"protein_change",aminoAcidChange:"amino_acid_change",endPos:"end_position",geneSymbol:"hugo_symbol",tumorFreq:"tumor_frequency",startPos:"start_position",keyword:"keyword",cosmic:"cosmic",validationStatus:"validation_status",mutationSid:"mutation_sid",normalAltCount:"normal_alt_count",variantAllele:"variant_allele",mutationId:"mutation_id",caseId:"sample_id",xVarLink:"xvar_link",pdbLink:"pdb_link",tumorAltCount:"tumor_alt_count",tumorRefCount:"tumor_ref_count",sequencingCenter:"center",chr:"chromosome"};return{parseInput:e,getSampleArray:o,getGeneList:r}}function PymolScriptGenerator(){function t(){return"reinitialize;"}function e(t){return"bg_color "+g(t)+";"}function n(t){return"fetch "+t+", async=0;"}function i(t){return v[t]}function a(t){return"color "+g(t)+", sele;"}function o(t){return"select chain "+t+";"}function r(t){return"select (chain "+t+") and (ss h);"}function l(t){return"select (chain "+t+") and (ss s);"}function u(t,e){return"select (resi "+t.join(",")+") and (chain "+e+");"}function s(t,e){return"select ((resi "+t.join(",")+") and (chain "+e+") and (not name c+n+o));"}function c(t){return"set transparency, "+t/10+", sele;\nset cartoon_transparency, "+t/10+", sele;\nset sphere_transparency, "+t/10+", sele;\nset stick_transparency, "+t/10+", sele;"}function d(){return"show spheres, sele; show sticks, sele; alter sele, vdw=0.50;"}function p(){return"hide spheres, sele; hide sticks, sele;"}function m(t){return"spectrum count, rainbow_rev, sele"}function h(t){return"util.cbaw sele;"}function f(){return"hide everything,not resn asp+glu+arg+lys+his+asn+thr+cys+gln+tyr+ser+gly+ala+leu+val+ile+met+trp+phe+pro"}function g(t){return t.replace("#","0x")}var v={ballAndStick:"hide everything; show spheres; show sticks; alter all, vdw=0.50",spaceFilling:"hide everything; show spheres;",ribbon:"hide everything; show ribbon;",cartoon:"hide everything; show cartoon;",trace:"hide everything; show ribbon;"};this.loadPdb=n,this.setScheme=i,this.setColor=a,this.selectChain=o,this.selectAlphaHelix=r,this.selectBetaSheet=l,this.rainbowColor=m,this.cpkColor=h,this.hideBoundMolecules=f,this.setTransparency=c,this.selectPositions=u,this.selectSideChains=s,this.enableBallAndStick=d,this.disableBallAndStick=p,this.reinitialize=t,this.bgColor=e}function AbstractDataProxy(t){var e=this;e._defaultOpts={initMode:"lazy",servletName:"",data:{}},e._options=jQuery.extend(!0,{},e._defaultOpts,t),e.init=function(){e.isFullInit()?e.fullInit(e._options):e.lazyInit(e._options)},e.lazyInit=function(t){},e.fullInit=function(t){},e.isFullInit=function(){return!("lazy"===e._options.initMode.toLowerCase())}}function MutationAlignerDataProxy(t){function e(t){r=t.data}function n(t,e){var n=t.pfamAccession;if(null==n)return void e(null);if(void 0==r[n]){if(i.isFullInit())return void e(null);var a=function(t){r[n]=t,e(t)};$.getJSON(o.servletName,t,a)}else e(r[n])}var i=this,a={servletName:"getMutationAligner.json"},o=jQuery.extend(!0,{},a,t);AbstractDataProxy.call(this,o),o=i._options;var r={};i.fullInit=e,i.getMutationAlignerData=n}function MutationDataProxy(t){function e(t){var e=t.data,n=new MutationCollection(e);d.processMutationData(n)}function n(){return m}function i(){return p}function a(){return c.geneList}function o(){return d}function r(t,e){var n=t.trim().split(/\s+/),i=[],a=[],o=d.getMutationGeneMap();if(_.each(n,function(t,e){t=t.toUpperCase();var n=o[t];void 0==n||0==n.length?i.push(t):a=a.concat(n)}),u.isFullInit())e(a);else{var r=function(t){var n=new MutationCollection(t);d.processMutationData(n),a=a.concat(t),e(a)};if(i.length>0){var l=c.params;l.geneList=i.join(" "),$.ajax({type:"POST",url:c.servletName,data:l,success:r,error:function(){console.log("[MutationDataProxy.getMutationData] error retrieving mutation data for genetic profiles: "+l.geneticProfiles),r([])},dataType:"json"})}else e(a)}}function l(){return!0}var u=this,s={servletName:"getMutationData.json",geneList:"",params:{}},c=jQuery.extend(!0,{},s,t);AbstractDataProxy.call(this,c),c=u._options;var d=new MutationDetailsUtil,p=c.geneList.trim().split(/\s+/),m=c.geneList.trim().split(/\s+/).sort();u.fullInit=e,u.getMutationData=r,u.getGeneList=n,u.getRawGeneList=a,u.getUnsortedGeneList=i,u.getMutationUtil=o,u.hasData=l}function PancanMutationDataProxy(t){function e(t){var e=t.data;c=e.byKeyword,d=e.byProteinChange,m=e.byGeneSymbol,p=e.byProteinPosition}function n(t,e,n){var a=t.cmd,o=t.q;if(null==a)n(null);else if("byKeywords"==a){var r=null==o?e.getAllKeywords():o.split(",");i(a,r,c,["keyword"],n)}else if("byHugos"==a){var l=null==o?e.getAllGenes():o.split(",");i(a,l,m,["hugo"],n)}else if("byProteinChanges"==a){var u=null==o?e.getAllProteinChanges():o.split(",");i(a,u,d,["protein_change"],n)}else if("byProteinPos"==a){var s=null==o?e.getAllProteinPosStarts():o.split(",");i(a,s,p,["hugo","protein_pos_start"],n)}else n(null)}function i(t,e,n,i,u){var c=o(e,n),d=r(c);d.length>0&&!l.isFullInit()?$.getJSON(s.servletName,{cmd:t,q:d.join(",")},function(t){a(t,c,n,i,u)}):a([],c,n,i,u)}function a(t,e,n,i,a){_.each(t,function(t,a){var o=[];_.each(i,function(e,n){o.push(t[e])});var r=o.join("_");null==n[r]&&(n[r]=[]),null==e[r]&&(e[r]=[]),n[r].push(t),e[r].push(t)});var o=[];_.each(e,function(t){o=o.concat(t)}),a(o)}function o(t,e){var n={};return _.each(t,function(t){n[t]=e[t]}),n}function r(t){var e=[];return _.each(_.keys(t),function(n){null==t[n]&&e.push(n)}),e}var l=this,u={servletName:"pancancerMutations.json"},s=jQuery.extend(!0,{},u,t);AbstractDataProxy.call(this,s),s=l._options;var c={},d={},p={},m={};l.fullInit=e,l.getPancanData=n}function PdbDataProxy(t){function e(t){var e=t.data;_.each(_.keys(e.pdbData),function(t){var n=PdbDataUtil.processPdbData(e.pdbData[t]);m[t]=n,h[t]=PdbDataUtil.allocateChainRows(n)}),f=e.infoData,g=e.summaryData,v=e.positionData}function n(t,e,n){var a=e.alignments,o=i(t,e);if(s.isFullInit()||null!=v[o])return void n(v[o]||{});var r=p.getProteinPositions(t),l={};_.each(r,function(t,n){t.start>-1&&t.start>=e.mergedAlignment.uniprotFrom&&t.start<=e.mergedAlignment.uniprotTo&&(l[t.start]=t.start),t.end>t.start&&t.end>=e.mergedAlignment.uniprotFrom&&t.end<=e.mergedAlignment.uniprotTo&&(l[t.end]=t.end)});var u=[];for(var c in l)u.push(l[c]);var m=[];a.each(function(t,e){m.push(t.alignmentId)});var h=function(e){var i={},a=p.getMutationGeneMap()[t];if(null!=e.positionMap)for(var r=0;r0?$.getJSON(d.servletName,{positions:u.join(" "),alignments:m.join(" ")},h):n({})}function i(t,e){var n=null;return e.alignments.length>0&&(n=t+"_"+e.alignments.at(0).pdbId+"_"+e.chainId),n}function a(t,e){if(s.isFullInit())return void e(m[t]);if(void 0==m[t]){var n=function(n){var i=PdbDataUtil.processPdbData(n);m[t]=i,e(i)};$.getJSON(d.servletName,{uniprotId:t},n)}else e(m[t])}function o(t,e){s.isFullInit()||void 0!=h[t]?e(h[t]):a(t,function(n){var i=PdbDataUtil.allocateChainRows(n);h[t]=i,e(i)})}function r(t,e){if(s.isFullInit()||void 0!=g[t])e(g[t]);else{var n=function(n){g[t]=n,e(n)};$.getJSON(d.servletName,{uniprotId:t,type:"summary"},n)}}function l(t,e){var n=function(t){var n=t&&t.alignmentCount>0;e(n)};r(t,n)}function u(t,e){var n=t.trim().split(/\s+/),i=[],a={};if(_.each(n,function(t,e){var n=f[t];void 0==n||0==n.length?i.push(t):a[t]=n}),s.isFullInit())return void e(a);var o={};if(i.length>0){var r=function(t){_.each(n,function(e,n){null!=t[e]&&(f[e]=t[e],a[e]=t[e])}),e(a)};o.pdbIds=i.join(" "),$.post(d.servletName,o,r,"json")}else e(a)}var s=this,c={servletName:"get3dPdb.json",mutationUtil:{}},d=jQuery.extend(!0,{},c,t);AbstractDataProxy.call(this,d),d=s._options;var p=d.mutationUtil,m={},h={},f={},g={},v={};s.fullInit=e,s.hasPdbData=l,s.getPdbData=a,s.getPdbRowData=o,s.getPdbInfo=u,s.getPositionMap=n}function PfamDataProxy(t){function e(t){r=t.data}function n(t,e){var n=t.geneSymbol;if(null==n)return void e(null);if(void 0==r[n]){if(i.isFullInit())return void e(null);var a=function(t){r[n]=t,e(t)};$.getJSON(o.servletName,t,a)}else e(r[n])}var i=this,a={servletName:"getPfamSequence.json"},o=jQuery.extend(!0,{},a,t);AbstractDataProxy.call(this,o),o=i._options;var r={};i.fullInit=e,i.getPfamData=n}function PortalDataProxy(t){function e(t){r=t.data}function n(t,e){var n={},i={};_.each(_.keys(t),function(e,a){null==r[e]?i[e]=t[e]:n[e]=r[e]});var a=function(t){_.each(_.keys(t),function(e,n){r[e]=t[e]}),_.isFunction(e)&&e(jQuery.extend(!0,{},n,t))};_.isEmpty(i)?a(n):$.getJSON(o.servletName,i,a)}var i=this,a={servletName:"portalMetadata.json"},o=jQuery.extend(!0,{},a,t);AbstractDataProxy.call(this,o),o=i._options;var r={};i.fullInit=e,i.getPortalData=n}function AdvancedDataTable(t){var e=this,n=null;e._defaultOpts={el:"",columns:{},columnOrder:[],columnVisibility:{},columnSearch:{},columnRender:{},columnSort:{},columnFilter:{},columnData:{},additionalData:{},columnTooltips:{},eventListeners:{},customSort:{},filteringDelay:0,dataTableOpts:{}},e._options=jQuery.extend(!0,{},e._defaultOpts,t),e._dispatcher={},_.extend(e._dispatcher,Backbone.Events),e._dataTable=null,e._visibilityValue=function(t){return"hidden"},e._searchValue=function(t){return!1},e.renderTable=function(t){var i=e._options.columnOrder,a=n=DataTableUtil.buildColumnIndexMap(i),o=DataTableUtil.buildColumnNameMap(e._options.columns),r=DataTableUtil.buildColumnVisMap(i,e._visibilityValue);e._visiblityMap=r;var l=DataTableUtil.buildColumnSearchMap(i,e._searchValue),u=DataTableUtil.getHiddenColumns(i,a,r),s=DataTableUtil.getExcludedColumns(i,a,r),c=DataTableUtil.getNonSearchableColumns(i,a,l);e._addSortFunctions(),e._dataTable=e._initDataTable($(e._options.el),t,e._options.columns,o,a,u,s,c),e._addEventListeners(a),e._options.filteringDelay>0&&e._dataTable.fnSetFilteringDelay(e._options.filteringDelay)},e._initDataTableOpts=function(t,e,n,i,a,o,r,l){return null},e._initDataTable=function(t,n,i,a,o,r,l,u){var s=e._initDataTableOpts(t,n,i,a,o,r,l,u),c=DataTableUtil.getColumnData(o,e._options.columnRender,e._options.columnSort,e._options.columnFilter,e._options.columnData);return s.aoColumnDefs=s.aoColumnDefs.concat(c),s=jQuery.extend(!0,{},e._options.dataTableOpts,s),t.dataTable(s)},e._addSortFunctions=function(){_.each(_.pairs(e._options.customSort),function(t){var e=t[0],n=t[1];jQuery.fn.dataTableExt.oSort[e]=n})},e._addEventListeners=function(t){null!=e.getDataTable()&&_.each(e._options.eventListeners,function(n){n(e.getDataTable(),e._dispatcher,t)})},e._addColumnTooltips=function(t){t=t||{};var n=$(e._options.el);_.each(_.keys(e._options.columnTooltips),function(i){if("excluded"!=e._visiblityMap[i]){var a=e._options.columnTooltips[i];_.isFunction(a)&&a(n,t)}})},e._loadAdditionalData=function(t){t=t||{};$(e._options.el);_.each(_.keys(e._options.additionalData),function(n){if("excluded"!=e._visiblityMap[n]){var i=e._options.additionalData[n];_.isFunction(i)&&i(t)}})},e.getColumnOptions=function(){return e._options.columns},e.getDataTable=function(){return e._dataTable},e.getIndexMap=function(){return n}}function Mutation3dVis(t,e){function n(){V=new Mol3DWrapper,V.init(t,G.appOptions),j.setViewer(V.getViewer()),j.setPdbUri(G.pdbUri)}function i(t){E=$(t);var e=E.find(".mutation-3d-vis-container");e.css("width",G.appOptions.width),e.css("height",G.appOptions.height+G.containerPadding),V.updateContainer(e)}function a(){U="ON"==U?"OFF":"ON";var t=j.spin(U);V.script(t)}function o(){var t=j.generateVisualStyleScript(O,R,G);t=t.concat(w(N)),t=t.join(" "),V.script(t)}function r(){if(null!=E){E.show();var t=parseInt(E.css("top"));0>t&&(null!=z&&z>0?E.css("top",z):E.css("top",0))}}function l(){if(null!=E){var t=parseInt(E.css("top"));t>0&&(z=t),E.css("top",-9999)}}function u(){null!=E&&(E.css({overflow:"hidden",height:G.minimizedHeight}),B=!0)}function s(){null!=E&&(E.css({overflow:"",height:""}),B=!1)}function c(){null!=E&&(B?s():u())}function d(){var t=parseInt(E.css("top")),e=-9999==t||E.is(":hidden");return!e}function p(t,e,n){var i=[];if(N={},!t||!e)return i;R=e,q=t,i=h(t,e);var a=[],o=function(){a.push(r),a=a.concat(j.generateVisualStyleScript(O,R,G)),a=a.join(" "),V.script(a,n),b()},r=j.loadPdb(t,o);return"$3Dmol"!=r&&o(),i}function m(){var t=[];if(N={},null==q||null==R)return t;t=h(q,R);var e=[];return e=e.concat(j.generateVisualStyleScript(O,R,G)),e=e.join(" "),V.script(e),t}function h(t,e){var n=f(t,e,G,j);return O=n.colorMap,n.mappedMutations}function f(t,e,n,i){var a=[],o={},r=n.mutationColor;for(var l in e.positionMap){var u=e.positionMap[l];if(_.isFunction(n.mutationColorMapper)&&(r=n.mutationColorMapper(l,t,e)),null!=r){null==o[r]&&(o[r]={});var s=i.scriptPosition(u);o[r][s]=s,a.push(l)}}return _.each(o,function(t,e,n){n[e]=_.values(t)}),{colorMap:o,mappedMutations:a}}function g(){if(1!=_.size(N))return!1;var t=[];return _.each(N,function(e){t=t.concat(D(e))}),t=t.join(" "),V.script(t),!0}function v(){var t=[];t.push(j.defaultCenter()),t=t.join(" "),V.script(t)}function b(){V.getViewer&&V.getViewer().resize()}function y(t){if(null==R)return!1;var e=t.mutations[0].mutationId,n=x(e);return n.length>0?(n=n.join(" "),V.script(n),!0):(T(),!1)}function T(){var t=[];t.push(j.zoom(G.defaultZoom)),t.push(j.defaultCenter()),t=t.join(" "),V.script(t)}function C(t,e){if(null==R)return 0;e&&(N={});var n=j.generateVisualStyleScript(O,R,G),i=0;return _.each(t,function(t,e){var n=t.mutations[0].mutationId,a=R.positionMap[n];null!=a&&(N[n]=a,i++)}),n=n.concat(w(N)),n=n.join(" "),V.script(n),i}function P(){var t=w(N);t=t.join(" "),V.script(t)}function S(){N={};var t=j.generateVisualStyleScript(O,R,G);t=t.join(" "),V.script(t)}function w(t){return j.generateHighlightScript(t,G.highlightColor,G,R)}function D(t){var e=[];return e.push(j.center(t,R.chainId)),e}function x(t){var e=[],n=R.positionMap[t];return null!=n&&(e.push(j.zoom(G.focusZoom)),e.push(j.center(n,R.chainId))),e}function M(){V.script(j.defaultZoomIn())}function A(){V.script(j.defaultZoomOut())}function I(){V.script(j.zoom(G.defaultZoom))}function F(t){V.script(j.zoom(t))}function L(t){G=jQuery.extend(!0,{},G,t)}function k(){var t=new PymolScriptGenerator,e=[];return e.push(t.reinitialize()),e.push(t.bgColor(G.appOptions.color)),e.push(t.loadPdb(q)),e=e.concat(t.generateVisualStyleScript(O,R,G)),e=e.concat(t.generateHighlightScript(N,G.highlightColor,G,R)),e.push(t.selectNone()),e=e.join("\n")}var E=null,V=null,B=!1,O=null,N={},R=null,q=null,U="OFF",z=null,H={appOptions:{width:400,height:300,debug:!1,color:"white"},pdbUri:"http://www.rcsb.org/pdb/files/",frame:"jsmol_frame.html",proteinScheme:"cartoon",restrictProtein:!1,defaultColor:"#DDDDDD",structureColors:{alphaHelix:"#FFA500",betaSheet:"#0000FF",loop:"#DDDDDD"},defaultTranslucency:5,chainColor:"#888888",chainTranslucency:0,colorProteins:"uniform",colorMutations:"byMutationType",mutationColor:"#8A2BE2",highlightColor:"#FFDD00",highlightGradient:["#FFDD00","#000000"],addGlowEffect:!1,displaySideChain:"highlighted",defaultZoom:100,focusZoom:250,containerPadding:10,minimizedHeight:10,mutationColorMapper:function(t,e,n){return"#FF0000"}},G=jQuery.extend(!0,{},H,e),j=new Mol3DScriptGenerator;return{init:n,show:r,hide:l,minimize:u,maximize:s,toggleSize:c,isVisible:d,reload:p,refresh:m,resizeViewer:b,focusOn:y,center:g,resetCenter:v,highlight:C,resetHighlight:S,refreshHighlight:P,zoomIn:M,zoomOut:A,zoomActual:I,zoomTo:F,resetFocus:T,updateContainer:i,toggleSpin:a,reapplyStyle:o,updateOptions:L,generatePymolScript:k}}function MutationDetailsTable(t,e,n,i){function a(t,a,r,l,u,s,c,d){var p=DataTableUtil.getColumnOptions(r,u),h={aaData:a,aoColumns:p,aoColumnDefs:[{bVisible:!1,aTargets:s},{bSearchable:!1,aTargets:d}],oColVis:{aiExclude:c},oTableTools:{aButtons:[{sExtends:"text",sButtonText:"Download",mColumns:o(r,c),fnCellRender:function(t,e,n,i){var a=t;return-1!=t.indexOf("<")&&-1!=t.indexOf(">")&&(a=$(t).text()),e===u.proteinChange&&(a=a.replace(/(\s)3D/,"")),a.trim()},fnClick:function(t,n){var i=this.fnGetTableData(n),a={filename:"mutation_table_"+e+".tsv",contentType:"text/plain;charset=utf-8",preProcess:!1};cbio.download.initDownload(i,a)}}]},fnDrawCallback:function(a){m._addColumnTooltips({gene:e,mutationUtil:n,dataProxies:i,additionalData:T}),m._addEventListeners(u);var o=a.oPreviousSearch.sSearch;v&&b!=o&&(g.trigger(MutationDetailsEvents.MUTATION_TABLE_FILTERED,t),y=o),b=o,g.trigger(MutationDetailsEvents.MUTATION_TABLE_REDRAWN,t),$(t).find('a[href=""]').remove(),$(t).find('span.mutation-table-additional-protein-change[alt=""]').remove()},fnRowCallback:function(t,e,n,i){var a=e[u.datum].mutation;$(t).attr("id",a.mutationId),$(t).addClass(a.mutationSid),$(t).addClass("mutation-table-data-row")},fnInitComplete:function(t,n){m._loadAdditionalData({gene:e,dataProxies:i,indexMap:m.getIndexMap(),additionalData:T,dataTable:this})},fnHeaderCallback:function(e,n,i,a,o){$(e).find("th").addClass("mutation-details-table-header"),m._addHeaderTooltips(e,l),g.trigger(MutationDetailsEvents.MUTATION_TABLE_HEADER_CREATED,t)}};return h}function o(t,e){for(var n=[],i=0;i<=_.keys(t).length;i++)n.push(i);return _.difference(n,e)}function r(t){var i=f.columnVisibility[t],a=i;return i?_.isFunction(i)&&(a=i(n,e)):a="hidden",a}function l(t){var e=f.columnSearch[t],n=e;return null==e?n=!1:_.isFunction(e)&&(n=e()),n}function u(t){null!=m.getDataTable()&&_.each(f.eventListeners,function(t){t(m.getDataTable(),g,n,e)})}function s(t){v=t}function c(){b="",y=""}function d(){return y}function p(t,e){var n=MutationViewsUtil.defaultTableTooltipOpts(),i={};jQuery.extend(!0,i,n),i.position={my:"bottom center",at:"top center",viewport:$(window)},$(t).find("th").each(function(){var t=$(this).text(),n=e[t];if(null!=n){var a=f.columns[n].tip,o={};_.isObject(a)?jQuery.extend(!0,o,i,a):(i.content=a,o=i),cbio.util.addTargetedQTip(this,o)}})}var m=this,h={el:"#mutation_details_table_d3",columns:{datum:{sTitle:"datum",tip:""},mutationId:{sTitle:"Mutation ID",tip:"Mutation ID",sType:"string"},mutationSid:{sTitle:"Mutation SID",tip:"",sType:"string"},caseId:{sTitle:"Sample ID",tip:"Sample ID",sType:"string"},cancerStudy:{sTitle:"Cancer Study",tip:"Cancer Study",sType:"string"},tumorType:{sTitle:"Cancer Type",tip:"Cancer Type",sType:"string"},proteinChange:{sTitle:"AA change",tip:"Protein Change",sType:"numeric"},mutationType:{sTitle:"Type",tip:"Mutation Type",sType:"string",sClass:"center-align-td"},cna:{sTitle:"Copy #",tip:"Copy-number status of the mutated gene",sType:"numeric",sClass:"center-align-td"},cosmic:{sTitle:"COSMIC",tip:"Overlapping mutations in COSMIC",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},mutationStatus:{sTitle:"MS",tip:"Mutation Status",sType:"string",sClass:"center-align-td"},validationStatus:{sTitle:"VS",tip:"Validation Status",sType:"string",sClass:"center-align-td"},mutationAssessor:{sTitle:"Mutation Assessor",tip:"Predicted Functional Impact Score (via Mutation Assessor) for missense mutations",sType:"numeric",sClass:"center-align-td",asSorting:["desc","asc"],sWidth:"2%"},sequencingCenter:{sTitle:"Center",tip:"Sequencing Center",sType:"string",sClass:"center-align-td"},chr:{sTitle:"Chr",tip:"Chromosome",sType:"string"},startPos:{sTitle:"Start Pos",tip:"Start Position",sType:"numeric",sClass:"right-align-td"},endPos:{sTitle:"End Pos",tip:"End Position",sType:"numeric",sClass:"right-align-td"},referenceAllele:{sTitle:"Ref",tip:"Reference Allele",sType:"string"},variantAllele:{sTitle:"Var",tip:"Variant Allele",sType:"string"},tumorFreq:{sTitle:"Allele Freq (T)",tip:"Variant allele frequency
in the tumor sample",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},normalFreq:{sTitle:"Allele Freq (N)",tip:"Variant allele frequency
in the normal sample",sType:"numeric",sClass:"right-align-td", -asSorting:["desc","asc"]},tumorRefCount:{sTitle:"Var Ref",tip:"Variant Ref Count",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},tumorAltCount:{sTitle:"Var Alt",tip:"Variant Alt Count",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},normalRefCount:{sTitle:"Norm Ref",tip:"Normal Ref Count",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},normalAltCount:{sTitle:"Norm Alt",tip:"Normal Alt Count",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},igvLink:{sTitle:"BAM",tip:"Link to BAM file",sType:"string",sClass:"center-align-td"},mutationCount:{sTitle:"#Mut in Sample",tip:"Total number of
nonsynonymous mutations
in the sample",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"],sWidth:"2%"},cBioPortal:{sTitle:"cBioPortal",tip:"Mutation frequency in cBioPortal",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]}},columnOrder:["datum","mutationId","mutationSid","caseId","cancerStudy","tumorType","proteinChange","mutationType","cna","cBioPortal","cosmic","mutationStatus","validationStatus","mutationAssessor","sequencingCenter","chr","startPos","endPos","referenceAllele","variantAllele","tumorFreq","normalFreq","tumorRefCount","tumorAltCount","normalRefCount","normalAltCount","igvLink","mutationCount"],columnVisibility:{datum:"excluded",proteinChange:"visible",caseId:function(t,e){return t.containsCaseId(e)?"visible":"hidden"},mutationType:function(t,e){return t.containsMutationType(e)?"visible":"hidden"},mutationAssessor:function(t,e){return t.containsFis(e)?"visible":"hidden"},cosmic:"visible",mutationCount:function(t,e){return t.containsMutationCount(e)?"visible":"hidden"},mutationId:"excluded",mutationSid:"excluded",cancerStudy:"excluded",cna:function(t,e){return t.containsCnaData(e)?"visible":"hidden"},tumorFreq:function(t,e){return t.containsAlleleFreqT(e)?"visible":"hidden"},igvLink:function(t,e){return t.containsIgvLink(e)?"visible":"excluded"},mutationStatus:function(t,e){return t.containsGermline(e)?"visible":"hidden"},validationStatus:function(t,e){return t.containsValidStatus(e)?"visible":"hidden"},tumorType:function(t,e){var n=t.distinctTumorTypeCount(e);return n>1?"visible":n>0?"hidden":"excluded"},cBioPortal:"excluded"},columnSearch:{caseId:!0,mutationId:!0,mutationSid:!0,cancerStudy:!0,proteinChange:!0,tumorType:!0,mutationType:!0},columnRender:{mutationId:function(t){var e=t.mutation;return e.mutationId},mutationSid:function(t){var e=t.mutation;return e.mutationSid},caseId:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getCaseId(e.caseId),i={};i.linkToPatientView=e.linkToPatientView,i.caseId=n.text,i.caseIdClass=n.style,i.caseIdTip=n.tip;var a=BackboneTemplateCache.getTemplateFn("mutation_table_case_id_template");return a(i)},proteinChange:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getProteinChange(e),i={};i.proteinChange=n.text,i.proteinChangeClass=n.style,i.proteinChangeTip=n.tip,i.additionalProteinChangeTip=n.additionalTip,i.pdbMatchLink=MutationDetailsTableFormatter.getPdbMatchLink(e);var a=BackboneTemplateCache.getTemplateFn("mutation_table_protein_change_template");return a(i)},cancerStudy:function(t){var e=t.mutation,n={};n.cancerStudy=e.cancerStudy,n.cancerStudyShort=e.cancerStudyShort,n.cancerStudyLink=e.cancerStudyLink;var i=BackboneTemplateCache.getTemplateFn("mutation_table_cancer_study_template");return i(n)},tumorType:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getTumorType(e),i={};i.tumorType=n.text,i.tumorTypeClass=n.style,i.tumorTypeTip=n.tip;var a=BackboneTemplateCache.getTemplateFn("mutation_table_tumor_type_template");return a(i)},mutationType:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getMutationType(e.mutationType),i={};i.mutationTypeClass=n.style,i.mutationTypeText=n.text;var a=BackboneTemplateCache.getTemplateFn("mutation_table_mutation_type_template");return a(i)},cosmic:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getCosmic(e.cosmicCount),i={};i.cosmicClass=n.style,i.cosmicCount=n.count;var a=BackboneTemplateCache.getTemplateFn("mutation_table_cosmic_template");return a(i)},cna:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getCNA(e.cna),i={};i.cna=n.text,i.cnaClass=n.style,i.cnaTip=n.tip;var a=BackboneTemplateCache.getTemplateFn("mutation_table_cna_template");return a(i)},mutationCount:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getIntValue(e.mutationCount),i={};i.mutationCount=n.text,i.mutationCountClass=n.style;var a=BackboneTemplateCache.getTemplateFn("mutation_table_mutation_count_template");return a(i)},normalFreq:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.normalAltCount),i=MutationDetailsTableFormatter.getAlleleFreq(e.normalFreq,e.normalAltCount,e.normalRefCount,"simple-tip"),a={};a.normalFreq=i.text,a.normalFreqClass=i.style,a.normalFreqTipClass=i.tipClass,a.normalTotalCount=i.total,a.normalAltCount=n.text;var o=BackboneTemplateCache.getTemplateFn("mutation_table_normal_freq_template");return o(a)},tumorFreq:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.tumorAltCount),i=MutationDetailsTableFormatter.getAlleleFreq(e.tumorFreq,e.tumorAltCount,e.tumorRefCount,"simple-tip"),a={};a.tumorFreq=i.text,a.tumorFreqClass=i.style,a.tumorFreqTipClass=i.tipClass,a.tumorTotalCount=i.total,a.tumorAltCount=n.text;var o=BackboneTemplateCache.getTemplateFn("mutation_table_tumor_freq_template");return o(a)},mutationAssessor:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getFis(e.functionalImpactScore,e.fisValue),i={};i.fisClass=n.fisClass,i.omaClass=n.omaClass,i.fisText=n.text;var a=BackboneTemplateCache.getTemplateFn("mutation_table_mutation_assessor_template");return a(i)},mutationStatus:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getMutationStatus(e.mutationStatus),i={};i.mutationStatusTip=n.tip,i.mutationStatusClass=n.style,i.mutationStatusText=n.text;var a=BackboneTemplateCache.getTemplateFn("mutation_table_mutation_status_template");return a(i)},validationStatus:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getValidationStatus(e.validationStatus),i={};i.validationStatusTip=n.tip,i.validationStatusClass=n.style,i.validationStatusText=n.text;var a=BackboneTemplateCache.getTemplateFn("mutation_table_validation_status_template");return a(i)},normalRefCount:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.normalRefCount),i={};i.normalRefCount=n.text,i.normalRefCountClass=n.style;var a=BackboneTemplateCache.getTemplateFn("mutation_table_normal_ref_count_template");return a(i)},normalAltCount:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.normalAltCount),i={};i.normalAltCount=n.text,i.normalAltCountClass=n.style;var a=BackboneTemplateCache.getTemplateFn("mutation_table_normal_alt_count_template");return a(i)},tumorRefCount:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.tumorRefCount),i={};i.tumorRefCount=n.text,i.tumorRefCountClass=n.style;var a=BackboneTemplateCache.getTemplateFn("mutation_table_tumor_ref_count_template");return a(i)},tumorAltCount:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.tumorAltCount),i={};i.tumorAltCount=n.text,i.tumorAltCountClass=n.style;var a=BackboneTemplateCache.getTemplateFn("mutation_table_tumor_alt_count_template");return a(i)},startPos:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getIntValue(e.startPos),i={};i.startPos=n.text,i.startPosClass=n.style;var a=BackboneTemplateCache.getTemplateFn("mutation_table_start_pos_template");return a(i)},endPos:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getIntValue(e.endPos),i={};i.endPos=n.text,i.endPosClass=n.style;var a=BackboneTemplateCache.getTemplateFn("mutation_table_end_pos_template");return a(i)},sequencingCenter:function(t){var e=t.mutation;return e.sequencingCenter},chr:function(t){var e=t.mutation;return e.chr},referenceAllele:function(t){var e=t.mutation;return e.referenceAllele},variantAllele:function(t){var e=t.mutation;return e.variantAllele},igvLink:function(t){var e=t.mutation,n={};n.igvLink=MutationDetailsTableFormatter.getIgvLink(e);var i=BackboneTemplateCache.getTemplateFn("mutation_table_igv_link_template");return i(n)},cBioPortal:function(t){t.mutation;if(null==t.cBioPortal){var e={loaderImage:"images/ajax-loader.gif",width:15,height:15},n=BackboneTemplateCache.getTemplateFn("mutation_table_placeholder_template");return n(e)}var i=MutationDetailsTableFormatter.getCbioPortal(t.cBioPortal),e={};e.portalFrequency=i.frequency,e.portalClass=i.style;var n=BackboneTemplateCache.getTemplateFn("mutation_table_cbio_portal_template");return n(e)}},columnTooltips:{simple:function(t,e){var n=MutationViewsUtil.defaultTableTooltipOpts();cbio.util.addTargetedQTip($(t).find(".simple-tip"),n)},cosmic:function(t,e){var n=e.gene,i=e.mutationUtil,a=MutationViewsUtil.defaultTableTooltipOpts();$(t).find(".mutation_table_cosmic").each(function(){var t=this,e=$(t).closest("tr.mutation-table-data-row").attr("id"),o=i.getMutationIdMap()[e],r={};jQuery.extend(!0,r,a),r.content={text:"NA"},r.events={render:function(e,i){var a={cosmic:o.cosmic,keyword:o.keyword,geneSymbol:n,total:$(t).text()},r=$(this).find(".qtip-content"),l=new CosmicTipView({el:r,model:a});l.render()}},cbio.util.addTargetedQTip(t,r)})},mutationAssessor:function(t,e){var n=(e.gene,e.mutationUtil),i=MutationViewsUtil.defaultTableTooltipOpts();$(t).find(".oma_link").each(function(){var t=$(this).closest("tr.mutation-table-data-row").attr("id"),e=n.getMutationIdMap()[t],a=MutationDetailsTableFormatter.getFis(e.functionalImpactScore,e.fisValue),o={};jQuery.extend(!0,o,i),o.content={text:"NA"},o.events={render:function(t,n){var i={impact:a.value,xvia:e.xVarLink.replace("getma.org","mutationassessor.org/r2"),msaLink:e.msaLink.replace("getma.org","mutationassessor.org/r2"),pdbLink:e.pdbLink.replace("getma.org","mutationassessor.org/r2")},o=$(this).find(".qtip-content"),r=new PredictedImpactTipView({el:o,model:i});r.render()}},cbio.util.addTargetedQTip(this,o)})},cBioPortal:function(t,e){var n=e.gene,i=e.mutationUtil,a=e.dataProxies.portalProxy,o=e.additionalData,r=function(e,a,o){$(t).find(".mutation_table_cbio_portal").each(function(t,r){var l=$(this).closest("tr.mutation-table-data-row").attr("id"),u=i.getMutationIdMap()[l],s=o||u.cancerStudy;cbio.util.addTargetedQTip(r,{content:{text:"pancancer mutation bar chart is broken"},events:{render:function(t,i){var o={pancanMutationFreq:e,cancerStudyMetaData:a,cancerStudyName:s,geneSymbol:n,keyword:u.keyword,proteinPosStart:u.proteinPosStart,mutationType:u.mutationType,qtipApi:i},r=$(this),l=new PancanMutationHistTipView({el:r,model:o});l.render()}},hide:{fixed:!0,delay:100},style:{classes:"qtip-light qtip-rounded qtip-shadow",tip:!0},position:{my:"center right",at:"center left",viewport:$(window)}})})};null!=o.pancanFrequencies&&a.getPortalData({cancerStudyMetaData:!0,cancerStudyName:!0},function(t){r(o.pancanFrequencies,t.cancerStudyMetaData,t.cancerStudyName)})}},eventListeners:{windowResize:function(t,e,n,i){$(window).one("resize",function(){t.is(":visible")&&t.fnAdjustColumnSizing()})},igvLink:function(t,e,n,i){$(t).find(".igv-link").off("click").on("click",function(t){t.preventDefault();var e=$(this).closest("tr.mutation-table-data-row").attr("id"),i=n.getMutationIdMap()[e],a=i.igvLink;$.getJSON(a,function(t){prepIGVLaunch(t.bamFileUrl,t.encodedLocus,t.referenceGenome,t.trackName)})})},proteinChange3d:function(t,e,n,i){$(t).find(".mutation-table-3d-link").off("click").on("click",function(t){t.preventDefault();var n=$(this).closest("tr.mutation-table-data-row").attr("id");e.trigger(MutationDetailsEvents.PDB_LINK_CLICKED,n)})},proteinChange:function(t,e,n,i){$(t).find(".mutation-table-protein-change a").off("click").on("click",function(t){t.preventDefault();var n=$(this).closest("tr.mutation-table-data-row").attr("id");e.trigger(MutationDetailsEvents.PROTEIN_CHANGE_LINK_CLICKED,n)})}},columnSort:{mutationId:function(t){var e=t.mutation;return e.mutationId},mutationSid:function(t){var e=t.mutation;return e.mutationSid},caseId:function(t){var e=t.mutation;return e.caseId},proteinChange:function(t){var e=t.mutation.proteinChange,n=e.match(/.*[A-Z]([0-9]+)[^0-9]+/);return n&&n.length>1?parseInt(n[1]):-(1/0)},cancerStudy:function(t){var e=t.mutation;return e.cancerStudy},tumorType:function(t){var e=t.mutation;return e.tumorType},mutationType:function(t){var e=t.mutation;return e.mutationType},cosmic:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.cosmicCount)},cna:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.cna)},mutationCount:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.mutationCount)},normalFreq:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignFloatValue(e.normalFreq)},tumorFreq:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignFloatValue(e.tumorFreq)},mutationAssessor:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignValueToPredictedImpact(e.functionalImpactScore,e.fisValue)},mutationStatus:function(t){var e=t.mutation;return e.mutationStatus},validationStatus:function(t){var e=t.mutation;return e.validationStatus},normalRefCount:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.normalRefCount)},normalAltCount:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.normalAltCount)},tumorRefCount:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.tumorRefCount)},tumorAltCount:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.tumorAltCount)},startPos:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.startPos)},endPos:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.endPos)},sequencingCenter:function(t){var e=t.mutation;return e.sequencingCenter},chr:function(t){var e=t.mutation;return e.chr},referenceAllele:function(t){var e=t.mutation;return e.referenceAllele},variantAllele:function(t){var e=t.mutation;return e.variantAllele},igvLink:function(t){var e=t.mutation;return e.igvLink},cBioPortal:function(t){var e=t.cBioPortal;return e||0}},columnFilter:{proteinChange:function(t){return t.mutation.proteinChange},mutationType:function(t){var e=MutationDetailsTableFormatter.getMutationType(t.mutation.mutationType);return e.text},cosmic:function(t){return t.mutation.cosmicCount},cna:function(t){return t.mutation.cna},mutationCount:function(t){return t.mutation.mutationCount},normalFreq:function(t){return t.mutation.normalFreq},tumorFreq:function(t){return t.mutation.tumorFreq},mutationAssessor:function(t){return t.mutation.functionalImpactScore},normalRefCount:function(t){return t.mutation.normalRefCount},normalAltCount:function(t){return t.mutation.normalAltCount},tumorRefCount:function(t){return t.mutation.tumorRefCount},tumorAltCount:function(t){return t.mutation.tumorAltCount},startPos:function(t){return t.mutation.startPos},endPos:function(t){return t.mutation.endPos}},columnData:{},additionalData:{cBioPortal:function(t){var e=t.dataProxies.pancanProxy,i=t.indexMap,a=t.dataTable,o=t.additionalData;e.getPancanData({cmd:"byProteinPos"},n,function(t){e.getPancanData({cmd:"byHugos"},n,function(e){var n=PancanMutationDataUtil.getMutationFrequencies({protein_pos_start:t,hugo:e});o.pancanFrequencies=n;var r=a.fnGetData();_.each(r,function(t,e){var o=t[i.datum].mutation.proteinPosStart;o>0?t[i.datum].cBioPortal=PancanMutationDataUtil.countByKey(n,o):t[i.datum].cBioPortal=0,a.fnUpdate(null,e,i.cBioPortal,!1,!1)}),r.length>0&&a.fnUpdate(null,0,i.cBioPortal)})})}},filteringDelay:600,dataTableOpts:{sDom:'<"H"<"mutation_datatables_filter"f>C<"mutation_datatables_info"i>>t<"F"<"mutation_datatables_download"T>>',bJQueryUI:!0,bPaginate:!1,bFilter:!0,sScrollY:"600px",bScrollCollapse:!0,oLanguage:{sInfo:"Showing _TOTAL_ mutation(s)",sInfoFiltered:"(out of _MAX_ total mutations)",sInfoEmpty:"No mutations to show"}}},f=jQuery.extend(!0,{},h,t);AdvancedDataTable.call(this,f),f=m._options;var g=m._dispatcher,v=!0,b="",y="",T={};this._initDataTableOpts=a,this._visibilityValue=r,this._searchValue=l,this._addEventListeners=u,this._addHeaderTooltips=p,this.setFilterEventActive=s,this.getManualSearch=d,this.cleanFilters=c,this.dispatcher=this._dispatcher}function MutationDiagram(t,e,n,i){var a=this;a.listeners={},a.dispatcher={},_.extend(a.dispatcher,Backbone.Events),a.options=jQuery.extend(!0,{},a.defaultOpts,e),a.dataProxies=i,a.geneSymbol=t,a.data=n,a.pileups=null==n?null:n.pileups,a.highlighted={},a.multiSelect=!1,a.svg=null,a.bounds=null,a.gData=null,a.gLine=null,a.gLabel=null,a.xScale=null,a.yScale=null,a.topLabel=null,a.xAxisLabel=null,a.yAxisLabel=null,a.xMax=null,a.yMax=null,a.maxCount=null,a.mutationColorMap={},a.mutationPileupMap={}}function MutationHistogram(t,e,n){MutationDiagram.call(this,t,e,n)}function MutationPdbPanel(t,e,n,i){function a(t,e,n,i,a){var l=tt;_.each(n,function(n,o){_.each(n,function(n,u){var s=n.chain;if(s.alignments.length>0){var c=e.colors[u%e.colors.length],d=e.marginTop+(a+o)*(e.chainHeight+e.chainPadding),p=r(t,s,c,e,i,d);p.datum(n),nt[PdbDataUtil.chainKey(n.pdbId,n.chain.chainId)]=p,null==J&&(J=p),l++}})}),tt=l,o(n,e)}function o(t,e){var i=[],a=[];_.each(t,function(t,e){_.each(t,function(t,e){i.push(t.pdbId),a.push(nt[PdbDataUtil.chainKey(t.pdbId,t.chain.chainId)])})}),n.getPdbInfo(i.join(" "),function(t){_.each(a,function(t,n){var i=e.chainTipFn;i(t)})})}function r(t,e,n,i,a,o){for(var r=t.append("g").attr("class","pdb-chain-group").attr("opacity",1),l=i.chainHeight,u=new MergedAlignmentSegmentor(e.mergedAlignment);u.hasNextSegment();){var s=u.getNextSegment(),c=Math.abs(a(s.start)-a(s.end)),d=a(s.start);if(s.type==PdbDataUtil.ALIGNMENT_GAP){var p=r.append("line").attr("stroke",i.chainBorderColor).attr("stroke-width",i.chainBorderWidth).attr("x1",d).attr("y1",o+l/2).attr("x2",d+c).attr("y2",o+l/2);p.datum({initPos:{x:d,y:o+l/2}})}else{var m=r.append("rect").attr("fill",n).attr("opacity",e.mergedAlignment.identityPerc).attr("stroke",i.chainBorderColor).attr("stroke-width",i.chainBorderWidth).attr("x",d).attr("y",o).attr("width",c).attr("height",l);m.datum({initPos:{x:d,y:o}})}}return r}function l(t,e){var n=e.marginLeft-e.labelYPaddingRightV,i=e.marginTop+e.labelYPaddingTopV,a="middle",o="rotate(270, "+n+","+i+")",r="vertical";K.lengtht){n=i;break}return-1==n&&(n=e.length-1),n}function p(t){var e=0,n=K.length;return e="auto"!=t?t:W.marginTop+W.marginBottom+n*(W.chainHeight+W.chainPadding)-W.chainPadding/2}function m(t){var e=0,n=K.length;return e=n>t?W.marginTop+t*(W.chainHeight+W.chainPadding)-W.chainPadding/2:p("auto")}function h(t,e,n){var i=t.append("svg");return i.attr("width",e),i.attr("height",n),i}function f(){K=PdbDataUtil.allocateChainRows(e),X=d(K.length,W.numRows);var t=$(W.el)[0],n=d3.select(t),o=W.numRows[0];at=m(o);var r=h(n,W.elWidth,at);Q=r,a(r,W,K.slice(0,o),i,0),et[0]=!0,0!=W.labelY&&l(r,W),it=g(K),y()}function g(t){var e={};return _.each(t,function(t,n){_.each(t,function(t,i){e[PdbDataUtil.chainKey(t.pdbId,t.chain.chainId)]=n})}),e}function v(t,e,n){Q.selectAll(t).on(e,n),null==j[t]&&(j[t]={}),j[t][e]=n}function b(t,e){Q.selectAll(t).on(e,null),j[t]&&j[t][e]&&delete j[t][e]}function y(){v(".pdb-chain-group","click",function(t,e){I(d3.select(this))})}function T(){for(var t in j){var e=Q.selectAll(t);for(var n in j[t])e.on(n,j[t][n])}}function C(){$(W.el).show()}function P(){$(W.el).hide()}function S(t){var e=m(W.numRows[t]),n=Q.attr("height");z(e,n),Q.transition().duration(W.animationDuration).attr("height",e).each("end",function(){H(e,n)}),at=e}function w(){var t=D();S(t)}function D(){var t=(Z+1)%(X+1);return et[t]||(a(Q,W,K.slice(W.numRows[Z],W.numRows[t]),i,W.numRows[Z]),T(),et[t]=!0),Z=t,t}function x(t){for(var e=-1,n=Z;t>n&&X>n;n++)e=D();-1!==e&&S(e)}function M(t,e){for(var n=-1,i=it[PdbDataUtil.chainKey(t,e)],a=0;aW.numRows[0]}function I(t){ot=t;var e=F(t);Q.selectAll(".pdb-selection-rectangle-group").remove();var n=Q.append("g").attr("class","pdb-selection-rectangle-group").attr("opacity",0),i=n.append("rect").attr("fill","none").attr("stroke",W.highlightBorderColor).attr("stroke-width",W.highlightBorderWidth).attr("x",e.x).attr("y",e.y).attr("width",e.width).attr("height",e.height);n.transition().duration(W.animationDuration).attr("opacity",1),i.datum({initPos:{x:e.x,y:e.y}}),Y.trigger(MutationDetailsEvents.PANEL_CHAIN_SELECTED,t)}function F(t){var e=1/0,n=-1,i=-1,a=-1;return t.selectAll("rect").each(function(t,o){var r=d3.select(this);i=parseFloat(r.attr("y")),a=parseFloat(r.attr("height"));var l=parseFloat(r.attr("x")),u=parseFloat(r.attr("width"));e>l&&(e=l),l+u>n&&(n=l+u)}),{x:e,y:i,width:n-e,height:a}}function L(t){null!=ot&&k(ot,t)}function k(t,e){var n=W.animationDuration;E(t,e),t==ot&&E(Q.selectAll(".pdb-selection-rectangle-group")),V(t);var i=m(1),a=Q.attr("height");z(i,a),Q.transition().duration(n).attr("height",i).each("end",function(){H(i,a)})}function E(t,e){var n=W.animationDuration,i=W.marginTop,a=W.chainHeight;t.selectAll("line").transition().duration(n).attr("y1",i+a/2).attr("y2",i+a/2),t.selectAll("rect").transition().duration(n).attr("y",i).each("end",function(){_.isFunction(e)&&e()})}function V(t,e){var n=W.animationDuration,i=t.datum(),a=PdbDataUtil.chainKey(i.pdbId,i.chain.chainId);Q.selectAll(".pdb-chain-group").transition().duration(n).attr("opacity",function(t){return PdbDataUtil.chainKey(t.pdbId,t.chain.chainId)===a?1:0}),Q.selectAll(".pdb-selection-rectangle-group").transition().duration(n).attr("opacity",function(e){return ot==t?1:0}),Q.select(".pdb-panel-y-axis-label-group").transition().duration(n).attr("opacity",0).each("end",function(){_.isFunction(e)&&e()})}function B(t,e,n){Q.selectAll(t).transition().duration(n).attr("y1",function(t){return e(this,t,"y1")}).attr("y2",function(t){return e(this,t,"y2")})}function O(t,e,n){Q.selectAll(t).transition().duration(n).attr("y",function(t){return e(this,t,"y")})}function N(t){var e=W.animationDuration;R(),q();var n=Q.attr("height");z(at,n),Q.transition().duration(e).attr("height",at).each("end",function(){_.isFunction(t)&&t(),H(at,n)})}function R(t){var e=W.animationDuration,n=function(t,e,n){return e.initPos.y};O(".pdb-chain-group rect",n,e),B(".pdb-chain-group line",n,e),O(".pdb-selection-rectangle-group rect",n,e),setTimeout(t,e+50)}function q(t){var e=W.animationDuration;Q.selectAll(".pdb-chain-group").transition().duration(e).attr("opacity",1),Q.selectAll(".pdb-selection-rectangle-group").transition().duration(e).attr("opacity",1),Q.selectAll(".pdb-panel-y-axis-label-group").transition().duration(e).attr("opacity",1).each("end",function(){_.isFunction(t)&&t()})}function U(){return ot}function z(t,e){Y.trigger(MutationDetailsEvents.PDB_PANEL_RESIZE_STARTED,t,e,W.maxHeight)}function H(t,e){Y.trigger(MutationDetailsEvents.PDB_PANEL_RESIZE_ENDED,t,e,W.maxHeight)}var G={el:"#mutation_pdb_panel_d3",elWidth:740,elHeight:"auto",maxHeight:200,numRows:[1/0],marginLeft:45,marginRight:30,marginTop:2,marginBottom:0,chainHeight:6,chainPadding:3,labelY:["PDB","Chains"],labelYFont:"sans-serif",labelYFontColor:"#2E3436",labelYFontSize:"12px",labelYFontWeight:"normal",labelYPaddingRightH:45,labelYPaddingTopH:7,labelYPaddingRightV:25,labelYPaddingTopV:20,labelAlignThreshold:5,chainBorderColor:"#666666",chainBorderWidth:.5,highlightBorderColor:"#FF9900",highlightBorderWidth:2,colors:["#3366cc"],animationDuration:1e3,chainTipFn:function(t){var e=t.datum();n.getPdbInfo(e.pdbId,function(n){var i=null;n&&(i=PdbDataUtil.generatePdbInfoSummary(n[e.pdbId],e.chain.chainId));var a=new PdbChainTipView({model:{pdbId:e.pdbId,pdbInfo:i.title,molInfo:i.molecule,chain:e.chain}}),o=a.compileTemplate(),r={content:{text:o},hide:{fixed:!0,delay:100},style:{classes:"qtip-light qtip-rounded qtip-shadow qtip-lightyellow"},position:{my:"bottom left",at:"top center",viewport:$(window)}};cbio.util.addTargetedQTip(t,r)})},yHelpTipFn:function(t){var e=BackboneTemplateCache.getTemplateFn("mutation_details_pdb_help_tip_template"),n=e({}),i={content:{text:n},hide:{fixed:!0,delay:100},style:{classes:"qtip-light qtip-rounded qtip-shadow qtip-lightyellow qtip-wide"},position:{my:"bottom left",at:"top center",viewport:$(window)}};cbio.util.addTargetedQTip(t,i)}},j={},Y={};_.extend(Y,Backbone.Events);var W=jQuery.extend(!0,{},G,t),Q=null,K=null,J=null,Z=0,X=null,tt=0,et=[],nt={},it={},at=0,ot=null;return{init:f,addListener:v,removeListener:b,getChainGroup:c,getDefaultChainGroup:s,show:C,hide:P,toggleHeight:w,expandToChainLevel:M,minimizeToChain:k,minimizeToHighlighted:L,restoreToFull:N,restoreChainPositions:R,fadeInAll:q,hasMoreChains:A,highlight:I,getHighlighted:U,dispatcher:Y}}function MutationPdbTable(t){function e(t,e,n,i,a,o,r,l){var s=DataTableUtil.getColumnOptions(n,a),c={aaData:e,aoColumns:s,aoColumnDefs:[{bVisible:!1,aTargets:o},{bSearchable:!1,aTargets:l}],oColVis:{aiExclude:r},fnDrawCallback:function(t){u._addColumnTooltips()},fnHeaderCallback:function(t,e,n,i,a){$(t).find("th").addClass("mutation-pdb-table-header")},fnRowCallback:function(t,e,n,i){var o=e[a.datum],r=PdbDataUtil.chainKey(o.pdbId,o.chain.chainId);p[r]=t,$(t).addClass("pdb-chain-table-data-row")},fnInitComplete:function(t,e){d.trigger(MutationDetailsEvents.PDB_TABLE_READY)}};return c}function n(t){var e=c.columnVisibility[t],n=e;return e?_.isFunction(e)&&(n=e()):n="hidden",n}function i(t){var e=c.columnSearch[t],n=e;return null==e?n=!1:_.isFunction(e)&&(n=e()),n}function a(){u.getDataTable().fnFilter("")}function o(t,e){var n=PdbDataUtil.chainKey(t,e);r();var i=p[n];$(i).addClass("row_selected"),m=i}function r(){$(c.el).find("tr").removeClass("row_selected")}function l(){return m}var u=this,s={el:"#mutation_pdb_table_d3",elWidth:740,columns:{datum:{sTitle:"datum",tip:""},pdbId:{sTitle:"PDB Id",tip:"",sType:"string"},chain:{sTitle:"Chain",tip:"",sType:"string"},uniprotPos:{sTitle:"Uniprot Positions",tip:"",sType:"numeric"},identityPercent:{sTitle:"Identity Percent",tip:"",sType:"numeric"},organism:{sTitle:"Organism",tip:"",sType:"string"},summary:{sTitle:"Summary",tip:"",sType:"string",sWidth:"65%"}},columnOrder:["datum","pdbId","chain","uniprotPos","identityPercent","organism","summary"],columnVisibility:{pdbId:"visible",chain:"visible",uniprotPos:"visible",identityPercent:"hidden",organism:"visible",summary:"visible",datum:"excluded"},columnSearch:{pdbId:!0,organism:!0,summary:!0},columnRender:{identityPercent:function(t){return Math.round(100*t.chain.mergedAlignment.identityPerc)},pdbId:function(t){var e=BackboneTemplateCache.getTemplateFn("mutation_pdb_table_pdb_cell_template");return e({pdbId:t.pdbId})},chain:function(t){var e=BackboneTemplateCache.getTemplateFn("mutation_pdb_table_chain_cell_template");return e({chainId:t.chain.chainId})},organism:function(t){return t.organism},summary:function(t){var e={summary:t.summary.title,molecule:t.summary.molecule},n=BackboneTemplateCache.getTemplateFn("mutation_pdb_table_summary_cell_template");return n(e)},uniprotPos:function(t){return t.chain.mergedAlignment.uniprotFrom+"-"+t.chain.mergedAlignment.uniprotTo}},columnTooltips:{simple:function(e){MutationViewsUtil.defaultTableTooltipOpts();cbio.util.addTargetedQTip($(e).find(".simple-tip"),t)}},eventListeners:{pdbLink:function(t,e,n){$(t).on("click",".pbd-chain-table-chain-cell a",function(i){i.preventDefault(),r();var a=$(i.target).closest("tr.pdb-chain-table-data-row");a.addClass("row_selected");var o=t.fnGetData(a[0]),l=o[n.datum];e.trigger(MutationDetailsEvents.TABLE_CHAIN_SELECTED,l.pdbId,l.chain.chainId)})}},columnSort:{identityPercent:function(t){return MutationDetailsTableFormatter.assignFloatValue(Math.round(100*t.chain.mergedAlignment.identityPerc))},pdbId:function(t){return t.pdbId},chain:function(t){return t.chain.chainId},organism:function(t){return t.organism},summary:function(t){return t.summary.title+t.summary.molecule},uniprotPos:function(t){return MutationDetailsTableFormatter.assignIntValue(t.chain.mergedAlignment.uniprotFrom)}},columnFilter:{identityPercent:function(t){return Math.round(100*t.chain.mergedAlignment.identityPerc)},summary:function(t){return t.summary.title+" "+t.summary.molecule},uniprotPos:function(t){return t.chain.mergedAlignment.uniprotFrom+"-"+t.chain.mergedAlignment.uniprotTo}},filteringDelay:0,dataTableOpts:{sDom:'<"H"<"mutation_pdb_datatable_info"i><"mutation_pdb_datatable_filter"f>>t',bJQueryUI:!0,bPaginate:!1,bFilter:!0,sScrollY:"200px",bScrollCollapse:!0,oLanguage:{sInfo:"Showing _TOTAL_ PDB chain(s)",sInfoFiltered:"(out of _MAX_ total chains)",sInfoEmpty:"No chains to show"}}},c=jQuery.extend(!0,{},s,t);AdvancedDataTable.call(this,c),c=u._options;var d=u._dispatcher,p={},m=null;this._initDataTableOpts=e,this._visibilityValue=n,this._searchValue=i,this.selectRow=o,this.cleanFilters=a,this.getSelectedRow=l,this.dispatcher=this._dispatcher}function PancanMutationHistogram(t,e,n,i,a){function o(t){return t.map(_.clone)}function r(t){return _.reduce(t,function(t,e){return t[e.cancer_study]=e,t},{})}function l(t){var e=v[t.cancer_study].num_sequenced_samples;return t.num_sequenced_samples=e,t.frequency=t.count/e,t}function u(t){var e=_.reduce(t,function(t,e){return t+e.frequency},0);return-1*e}function s(t){var e=t[0].cancer_type;if(!_.every(t,function(t){return t.cancer_type===e}))throw new Error("not all data in a group have the same cancer type");return e}function c(t){function e(t){return{cancer_study:t,count:0,cancer_type:v[t].cancer_type,num_sequenced_samples:v[t].num_sequenced_samples}}var n=r(t);return _.chain(b).reduce(function(t,e){return _.has(n,e)||t.push(e),t},[]).map(e).value()}function d(t){return t.concat(c(t))}function p(){var t,e=_.find(M[0],function(t){return t.cancer_study===a.this_cancer_study});try{t=e.cancer_type}catch(n){throw new Error(n+": could not find this the corresponding datum for this cancer study, ["+a.this_cancer_study+"]")}var i=function(t){return _.find(t,function(t){return t.cancer_study===a.this_cancer_study})},o=_.zip.apply(null,M);o=_.find(o,i);var r=u(o);L.append("text").text("*").attr("id","star").attr("x",V(a.this_cancer_study)).attr("y",N(-1*r)+10).style("font-family","Helvetica Neue, Helvetica, Arial, sans-serif").style("font-size",3*V.rangeBand()+"px")}function m(t){var e=d3.select(t).selectAll(".mouseOver").data(b).enter().append("rect").attr("class","mouseOver").attr("y",a.margin.top).attr("x",function(t){return V(t)+a.margin.left}).attr("opacity","0").attr("height",F+5).attr("width",V.rangeBand()).on("mouseover",function(){d3.select(this).attr("opacity","0.25")}).on("mouseout",function(){ -d3.select(this).attr("opacity","0")});e.each(function(t){$(this).qtip({content:{text:"mouseover failed"},position:{my:"left top",at:"center right",viewport:$(window)},style:{classes:"qtip-light qtip-rounded qtip-shadow qtip-wide"},hide:{fixed:!0,delay:100},events:{render:function(e,n){var i=g(t).map(function(t){return t[0].__data__}),a=i.filter(function(t){return _.has(t,"keyword")})[0]||{},o=i.filter(function(t){return!_.has(t,"keyword")})[0]||{},r=o.cancer_study,l=v[r].num_sequenced_samples,u="

"+r+"

"+f(a,o,l);n.set("content.text",u)}}})})}function h(t,e){var n=t.count||0;"frequency"in t||(t.frequency=n/e);var i=(100*t.frequency).toFixed(1)+"%";return _.template("{{percent}} ({{count}} of {{total}} sequenced samples)")({percent:i,count:n,total:e})}function f(t,e,n){return"

"+C+": "+h(t,n)+"

Other "+Y+" mutations: "+h(e,n)+"

"}function g(t){return z.filter(function(e){return e.cancer_study===t})}a=a||{},a=a.sparkline?_.extend({margin:{top:-12,right:0,bottom:0,left:0},width:30,height:12,this_cancer_study:void 0},a):_.extend({margin:{top:6,right:10,bottom:20,left:40},width:600,height:300,this_cancer_study:void 0},a);var v=r(n),b=_.keys(v),y=o(t),T=o(e),C=y[0].hugo+" "+y[0].protein_pos_start;y=d(y).map(function(t){return t.keyword=C,t}),T=d(T);var P={bykeyword:r(y),bygene:r(T)},S=_.intersection(_.keys(P.bykeyword),_.keys(P.bygene));if(y=[],T=[],_.each(S,function(t){y.push(P.bykeyword[t]),T.push(P.bygene[t])}),T.length!==y.length)throw new Error("must be same length");if(T.length!==b.length)throw new Error("there must be a datum for every cancer study and visa versa");T.forEach(function(t){var e=P.bykeyword[t.cancer_study],n=t.count-e.count;if(0>n)throw new Error("more mutations for a particular keyword than for all keywords of a particular gene");t.count=n});var w=_.reduce(T,function(t,e){return t+e.count},0),D=_.reduce(y,function(t,e){return t+e.count},0),x=_.reduce(v,function(t,e){return t+e.num_sequenced_samples},0);_.mixin({unzip:function(t){return _.zip.apply(_,t)}});var M=y.concat(T);try{M=_.chain(M).map(l).groupBy(function(t){return t.cancer_study}).map(_.identity).sortBy(s).unzip().value()}catch(A){throw new Error(A)}var I=a.width-a.margin.left-a.margin.left,F=a.height-a.margin.top-a.margin.bottom,L=d3.select(i).append("svg").attr("width",a.width).attr("height",a.height).append("g").attr("transform","translate("+a.margin.left+","+a.margin.top+")"),k=d3.layout.stack().x(function(t){return t.cancer_study}).y(function(t){return t.frequency}),E=k(M),V=d3.scale.ordinal().domain(M[0].map(function(t){return t.cancer_study})).rangeBands([0,I],.1),B=.2,O=a.sparkline?B:d3.max(E,function(t){return d3.max(t,function(t){return t.y0+t.y})}),N=d3.scale.linear().domain([0,O]).range([F,0]).clamp(!0),R="LimeGreen",q="Green",U=L.selectAll(".layer").data(E).enter().append("g").attr("class","layer").style("fill",function(t,e){return[q,R][e]}),z=U.selectAll("rect").data(function(t){return t}).enter().append("rect").attr("x",function(t){return V(t.cancer_study)}).attr("y",function(t){return N(t.y0+t.y)}).attr("width",function(t){return V.rangeBand()}).attr("height",function(t){return N(t.y0)-N(t.y0+t.y)});if(a.sparkline)return{el:i,qtip:function(){throw new Error("don't qtip a sparkline")}};var H=d3.format(O>.1?".0%":".1%"),G=d3.svg.axis().scale(N).tickFormat(H).orient("left");G.tickSize(G.tickSize(),0,0);var j=function(){function t(t){return{cancer_type:t.cancer_type,start:t.cancer_study,end:t.cancer_study,color:v[t.cancer_study].color}}var e=M[0][0];return _.chain(M[0]).reduce(function(e,n){var i=_.last(e);return i.cancer_type!==n.cancer_type?e.concat(t(n)):i.cancer_type===n.cancer_type?(i.end=n.cancer_study,e):void 0},[t(e)]).value()}();L.selectAll("line").data(j).enter().append("line").attr("x1",function(t){return V(t.start)}).attr("x2",function(t){return V(t.end)+V.rangeBand()}).attr("y1",F+a.margin.bottom/3).attr("y2",F+a.margin.bottom/3).style("stroke-width",5).style("stroke",function(t){return t.color});var Y=(L.append("g").call(G).attr("stroke","#000").attr("shape-rendering","crispEdges"),_.find(E[0],function(t){return void 0!==t.hugo}).hugo),C=_.find(E[0],function(t){return void 0!==t.keyword}).keyword;return _.isUndefined(a.this_cancer_study)||p(),{el:i,qtip:m,overallCountText:function(){return f({count:D},{count:w},x)}}}function MainMutationController(t,e){function n(){e.dispatcher.on(MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED,o),e.dispatcher.on(MutationDetailsEvents.LOLLIPOP_DESELECTED,r),e.dispatcher.on(MutationDetailsEvents.LOLLIPOP_SELECTED,l),e.dispatcher.on(MutationDetailsEvents.DIAGRAM_PLOT_UPDATED,a),t.addResetCallback(i)}function i(n){e.resetPlot(),t.hideFilterInfo()}function a(){e.isFiltered()?t.showFilterInfo():t.hideFilterInfo()}function o(){e.isFiltered()||t.hideFilterInfo()}function r(t,n){0==e.getSelectedElements().length&&o()}function l(e,n){t.showFilterInfo()}n()}function Mutation3dController(t,e,n,i,a,o,r,l,u,s){function c(){l.dispatcher.on(MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED,D),l.dispatcher.on(MutationDetailsEvents.LOLLIPOP_DESELECTED,x),l.dispatcher.on(MutationDetailsEvents.LOLLIPOP_SELECTED,M),l.dispatcher.on(MutationDetailsEvents.LOLLIPOP_MOUSEOVER,A),l.dispatcher.on(MutationDetailsEvents.LOLLIPOP_MOUSEOUT,I),l.dispatcher.on(MutationDetailsEvents.DIAGRAM_PLOT_UPDATED,w),l.dispatcher.on(MutationDetailsEvents.DIAGRAM_PLOT_RESET,S),u.dispatcher.on(MutationDetailsEvents.PDB_LINK_CLICKED,L),u.dispatcher.on(MutationDetailsEvents.PROTEIN_CHANGE_LINK_CLICKED,F),i.addInitCallback(m),n.dispatcher.on(MutationDetailsEvents.VIEW_3D_PANEL_CLOSED,p),n.dispatcher.on(MutationDetailsEvents.VIEW_3D_STRUCTURE_RELOADED,v),t.dispatcher.on(MutationDetailsEvents.GENE_TAB_SELECTED,d)}function d(t){n&&(n.resetPanelPosition(),n.hideView())}function p(){N&&N.hideView()}function m(t){B(),null!=n&&(n.resetPanelPosition(),n.maximizeView())}function h(t,e,n){t>n&&N.toggleScrollBar(n)}function f(t,e,n){n>=t&&N.toggleScrollBar(-1),e!=t&&N.scrollToSelected()}function g(t){q&&N.scrollToSelected();var e=t.datum();null!=n&&(n.maximizeView(),n.updateView(s,e.pdbId,e.chain)),q||null==R||(R.resetFilters(),R.selectChain(e.pdbId,e.chain.chainId),R.scrollToSelected()),q=!1}function v(){i.isVisible()&&l.isHighlighted()&&V()}function b(t,e){t&&e&&(N.selectChain(t,e),q=!0)}function y(){N.pdbPanel.minimizeToHighlighted()}function T(t,e){t&&e&&N.pdbPanel.minimizeToChain(N.pdbPanel.getChainGroup(t,e))}function C(t){null==R&&null!=N&&t.length>0&&(R=N.initPdbTableView(t,function(t,e){e.dispatcher.on(MutationDetailsEvents.PDB_TABLE_READY,P),R=t}),R.pdbTable.dispatcher.on(MutationDetailsEvents.TABLE_CHAIN_SELECTED,b),R.pdbTable.dispatcher.on(MutationDetailsEvents.TABLE_CHAIN_MOUSEOUT,y),R.pdbTable.dispatcher.on(MutationDetailsEvents.TABLE_CHAIN_MOUSEOVER,T)),null!=N&&null!=R&&(N.toggleTableControls(),R.toggleView())}function P(){if(null!=N){var t=N.getSelectedChain();if(null!=t){var e=t.datum();R.selectChain(e.pdbId,e.chain.chainId),R.scrollToSelected()}}}function S(){n&&n.isVisible()&&n.refreshView()}function w(){n&&n.isVisible()&&n.refreshView()}function D(){n&&n.isVisible()&&(n.resetHighlight(),n.hideResidueWarning())}function x(t,e){l.isHighlighted()?M():D()}function M(t,e){n&&n.isVisible()&&V()}function A(t,e){if(n&&n.isVisible()){var i=E();i.push(t),$(i,!0)}}function I(t,e){x(t,e)}function F(t){var e=k(t);e&&n&&n.isVisible()&&V()}function L(t){var e=k(t);e&&B(e.pdbMatch.pdbId,e.pdbMatch.chainId)}function k(t){var e=r.getMutationIdMap(),n=e[t];return n&&(l.clearHighlights(),l.highlightMutation(n.mutationSid)),n}function E(){var t=[];return _.each(l.getSelectedElements(),function(e,n){t=t.concat(e.datum())}),t}function V(){var t=E();$(t)}function $(t,e){var i=n.highlightView(t,!0),a=t.length-i;e||(a>0?n.showResidueWarning(a,t.length):n.hideResidueWarning())}function B(t,a){var r=i.model.uniprotId,l=function(i){null==N&&(N=e.initPdbPanelView(i),N.pdbPanel.dispatcher.on(MutationDetailsEvents.PANEL_CHAIN_SELECTED,g),N.pdbPanel.dispatcher.on(MutationDetailsEvents.PDB_PANEL_RESIZE_STARTED,h),N.pdbPanel.dispatcher.on(MutationDetailsEvents.PDB_PANEL_RESIZE_ENDED,f),N.addInitCallback(function(t){C(i)})),null!=n&&null!=N&&i.length>0&&(O(),N.showView(),t&&a?N.selectChain(t,a):N.selectDefaultChain(),N.autoCollapse())};o.getPdbData(r,l)}function O(){var t=function(t,e,n){return l.mutationColorMap[t]};a.updateOptions({mutationColorMapper:t})}var N=null,R=null,q=!1;c()}function MutationDetailsController(t,e,n,i,a,o){function r(){t.dispatcher.on(MutationDetailsEvents.GENE_TAB_SELECTED,l),t.dispatcher.on(MutationDetailsEvents.GENE_TABS_CREATED,u)}function l(t){null==h[t]&&s(t,n,i,a)}function u(){var e=t.$el.find(".mutation-3d-container");if(o){var r=new Mutation3dVisView({el:e,mut3dVis:o,pdbProxy:m,mutationProxy:d});r.render(),f=r}else $(e).hide();var l=d.getGeneList();s(l[0],n,i,a)}function s(n,i,a,r){var l=function(l,u,s){u=c(u,d.getMutationUtil(),s);var p=d.getMutationUtil(),g={geneSymbol:n,mutationData:u,dataProxies:e,sequence:l,sampleArray:i,diagramOpts:a,tableOpts:r},v=new MainMutationView({el:"#mutation_details_"+cbio.util.safeProperty(n),model:g});v.render(),h[n].mainMutationView=v;var b=v.initComponents(f);(null==u||0==u.length)&&(v.showNoDataInfo(),b.tableView.hideView()),new MainMutationController(v,b.diagram),new MutationDetailsTableController(b.tableView,b.diagram,t),o&&f&&new Mutation3dController(t,v,f,b.view3d,o,m,p,b.diagram,b.tableView.tableUtil,n),new MutationDiagramController(b.diagram,b.tableView.tableUtil,p)};d.getMutationData(n,function(t){h[n]={},null==t&&(t=[]);var e=d.getMutationUtil().dataFieldCount(n,"uniprotAcc",["NA"]),i=null,a={geneSymbol:n};e.length>0&&(i=e[0].uniprotAcc),i&&(a.uniprotAcc=i),p.getPfamData(a,function(e){if(null==e)return void console.log("[warning] no pfam data found: %o",a);var n=e[0];if(m){var i=n.metadata.identifier;m.getPdbRowData(i,function(e){l(n,t,e)})}else l(n,t)})})}function c(t,e,n){if(!n)return t;var i=e.getMutationIdMap();return _.each(t,function(t,e){if(null==t)return void console.log("warning [processMutationData]: mutation (at index %d) is null.",e);var a=i[t.mutationId],o=PdbDataUtil.mutationToPdb(a,n);t.pdbMatch=o,a.pdbMatch=o}),t}var d=e.mutationProxy,p=e.pfamProxy,m=e.pdbProxy,h={},f=null;r()}function MutationDetailsTableController(t,e,n){function i(){e.dispatcher.on(MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED,o),e.dispatcher.on(MutationDetailsEvents.LOLLIPOP_DESELECTED,r),e.dispatcher.on(MutationDetailsEvents.LOLLIPOP_SELECTED,l),e.dispatcher.on(MutationDetailsEvents.LOLLIPOP_MOUSEOVER,u),e.dispatcher.on(MutationDetailsEvents.LOLLIPOP_MOUSEOUT,s),e.dispatcher.on(MutationDetailsEvents.DIAGRAM_PLOT_RESET,a),n.dispatcher.on(MutationDetailsEvents.GENE_TAB_SELECTED,c)}function a(){t&&t.resetFilters()}function o(){t&&(t.clearHighlights(),t.rollBack())}function r(n,i){if(t){t.clearHighlights();var a=[];_.each(e.getSelectedElements(),function(t,e){a=a.concat(t.datum().mutations)}),a.length>0?t.filter(a):t.rollBack()}}function l(n,i){if(t){t.clearHighlights();var a=[];_.each(e.getSelectedElements(),function(t,e){a=a.concat(t.datum().mutations)}),t.filter(a)}}function u(e,n){t&&t.highlight(e.mutations)}function s(e,n){t&&t.clearHighlights()}function c(e){if(t){var n=t.tableUtil.getDataTable();n.is(":visible")&&n.fnAdjustColumnSizing()}}i()}function MutationDiagramController(t,e,n){function i(){e.dispatcher.on(MutationDetailsEvents.MUTATION_TABLE_FILTERED,a)}function a(e){var n=[],i=[];try{i=$(e).DataTable().rows({filter:"applied"}).data()}catch(a){i=$(e).dataTable()._("tr",{filter:"applied"})}if(_.each(i,function(t,e){var i=t[0].mutation;i&&n.push(i)}),null!==t){var o=new MutationCollection(n);t.updatePlot(PileupUtil.convertToPileups(o))}}i()}function MutationMapper(t){function e(t){a.proxy.mutationProxy.options.geneList=a.data.geneList.join(" ");var e=DataProxyUtil.initDataProxies(a.proxy,t),i={mutationProxy:e.mutationProxy,sampleArray:a.data.sampleList,tableOpts:a.view.mutationTable,diagramOpts:a.view.mutationDiagram},o={el:a.el,model:i,mut3dVis:t},r=new MutationDetailsView(o);n=r;new MutationDetailsController(r,e,i.sampleArray,i.diagramOpts,i.tableOpts,t);r.render()}var n=null,i={el:"#mutation_details",data:{geneList:[],sampleList:[]},view:{mutationDiagram:{},mutationTable:{},pdbPanel:{},pdbTable:{},vis3d:{}},proxy:{pfamProxy:{instance:null,instanceClass:PfamDataProxy,options:{data:{}}},mutationProxy:{instance:null,instanceClass:MutationDataProxy,options:{data:{},params:{},geneList:""}},pdbProxy:{instance:null,instanceClass:PdbDataProxy,options:{data:{pdbData:{},infoData:{},summaryData:{},positionData:{}},mutationUtil:{}}},pancanProxy:{instance:null,instanceClass:PancanMutationDataProxy,options:{data:{byKeyword:{},byProteinChange:{},byProteinPosition:{},byGeneSymbol:{}}}},mutationAlignerProxy:{instance:null,instanceClass:MutationAlignerDataProxy,options:{data:{}}},portalProxy:{instance:null,instanceClass:PortalDataProxy,options:{data:{}}}}},a=jQuery.extend(!0,{},i,t);this.init=e,this.getView=function(){return n}}var DataTableUtil=function(){function t(t){var e={};return _.each(t,function(t,n){null==e[t]&&(e[t]=n)}),e}function e(t){var e={};return _.each(_.pairs(t),function(t,n){var i=t[0],a=t[1];null!=a.sTitle&&a.sTitle.length>0&&(e[a.sTitle]=i)}),e}function n(t,e){var n={};return _.each(t,function(t,i){null==n[t]&&(_.isFunction(e)?n[t]=e(t):n[t]="hidden")}),n}function i(t,e){var n={};return _.each(t,function(t,i){null==n[t]&&(n[t]=_.isFunction(e)&&e(t))}),n}function a(t,e,n){var i=[];return _.each(t,function(t,a){"visible"!=n[t]&&i.push(e[t])}),i}function o(t,e,n){var i=[];return _.each(t,function(t,a){"excluded"==n[t]&&i.push(e[t])}),i}function r(t,e,n){var i=[];return _.each(t,function(t,a){n[t]===!1&&i.push(e[t])}),i}function l(t,e){var n=[];return _.each(_.pairs(t),function(t){var i=t[0],a=t[1],o=e[i];if(null!=o){var r={fnRender:function(t){var n=t.aData[e.datum];return a(t,n)},aTargets:[o]};n.push(r)}}),n}function u(t,e,n,i,a){var o={};return _.each(_.pairs(e),function(e){var a=e[0],r=e[1],l=n[a],u=i[a],s=t[a],c=function(t){return null!=l?l(t):r(t)};if(null!=s){var d={mData:function(e,n,i){var a=e[t.datum];return"set"===n?null:"display"===n?r(a):"sort"===n?c(a):"filter"===n?null!=u?u(a):c(a):e[s]},aTargets:[s]};o[a]=d}}),_.each(_.pairs(a),function(e){var n=e[0],i=e[1],a=t[n],r={mData:function(e,n,a){return i(e,n,a,t)},aTargets:[a]};o[n]=r}),_.values(o)}function s(t,e){var n=[];return _.each(_.pairs(t),function(t){var i=t[0],a=t[1],o=e[i];o>0&&(n[o]=a)}),n}function c(t){var e=$(t).attr("alt"),n=parseFloat(e);return isNaN(n)&&(n=""),n}function d(t){return-1!=t.indexOf("label")?$(t).find("label").text().trim()||$(t).text().trim():-1}function p(t){return-1!=t.indexOf("label")?parseInt($(t).text()):-1}function m(t){return-1!=t.indexOf("label")?parseFloat($(t).text()):-1}function h(t,e,n,i){return n>=0?i>=0?n==i?0:i>n?-1:1:-1:i>=0?1:t==e?0:e>t?1:-1}function f(t,e,n,i){return n>=0?i>=0?n==i?0:i>n?1:-1:-1:i>=0?1:t==e?0:e>t?-1:1}return{buildColumnIndexMap:t,buildColumnNameMap:e,buildColumnVisMap:n,buildColumnSearchMap:i,getHiddenColumns:a,getExcludedColumns:o,getNonSearchableColumns:r,getColumnOptions:s,getColumnRenderers:l,getColumnData:u,compareSortAsc:h,compareSortDesc:f,getAltTextValue:c,getLabelTextValue:d,getLabelTextIntValue:p,getLabelTextFloatValue:m}}(),MutationViewsUtil=function(){function t(t,e,n,i,a){var o=new MutationMapper(e),r=!1;return $(t).is(":visible")&&(o.init(a),r=!0),$(n).bind("tabsactivate",function(t,e){e.newTab.text().trim().toLowerCase()==i.toLowerCase()&&(r?o.getView().refreshGenesTab():(o.init(a),r=!0))}),o}function e(){return{mutationType:i,validationStatus:a,mutationStatus:o,omaScore:r,cna:l}}function n(){return{content:{attr:"alt"},show:{event:"mouseover"},hide:{fixed:!0,delay:100,event:"mouseout"},style:{classes:"mutation-details-tooltip qtip-shadow qtip-light qtip-rounded"},position:{my:"top left",at:"bottom right",viewport:$(window)}}}var i={missense_mutation:{label:"Missense",style:"missense_mutation"},nonsense_mutation:{label:"Nonsense",style:"trunc_mutation"},nonstop_mutation:{label:"Nonstop",style:"trunc_mutation"},frame_shift_del:{label:"FS del",style:"trunc_mutation"},frame_shift_ins:{label:"FS ins",style:"trunc_mutation"},in_frame_ins:{label:"IF ins",style:"inframe_mutation"},in_frame_del:{label:"IF del",style:"inframe_mutation"},splice_site:{label:"Splice",style:"trunc_mutation"},other:{style:"other_mutation"}},a={valid:{label:"V",style:"valid",tooltip:"Valid"},validated:{label:"V",style:"valid",tooltip:"Valid"},wildtype:{label:"W",style:"wildtype",tooltip:"Wildtype"},unknown:{label:"U",style:"unknown",tooltip:"Unknown"},not_tested:{label:"U",style:"unknown",tooltip:"Unknown"},none:{label:"U",style:"unknown",tooltip:"Unknown"},na:{label:"U",style:"unknown",tooltip:"Unknown"}},o={somatic:{label:"S",style:"somatic",tooltip:"Somatic"},germline:{label:"G",style:"germline",tooltip:"Germline"},unknown:{label:"U",style:"unknown",tooltip:"Unknown"},none:{label:"U",style:"unknown",tooltip:"Unknown"},na:{label:"U",style:"unknown",tooltip:"Unknown"}},r={h:{label:"High",style:"oma_high",tooltip:"High"},m:{label:"Medium",style:"oma_medium",tooltip:"Medium"},l:{label:"Low",style:"oma_low",tooltip:"Low"},n:{label:"Neutral",style:"oma_neutral",tooltip:"Neutral"}},l={"-2":{label:"DeepDel",style:"cna-homdel",tooltip:"Deep deletion"},"-1":{label:"ShallowDel",style:"cna-hetloss",tooltip:"Shallow deletion"},0:{label:"Diploid",style:"cna-diploid",tooltip:"Diploid / normal"},1:{label:"Gain",style:"cna-gain",tooltip:"Low-level gain"},2:{label:"AMP",style:"cna-amp",tooltip:"High-level amplification"},unknown:{label:"NA",style:"cna-unknown",tooltip:"CNA data is not available for this gene"}};return{initMutationMapper:t,defaultTableTooltipOpts:n,getVisualStyleMaps:e}}(),MutationDetailsTableFormatter=function(){function t(t){return e(F,t)}function e(t,e){var n,i,a;return null!=t[e]?(n=t[e].style,i=t[e].label,a=t[e].tooltip):(n=t.unknown.style,i=t.unknown.label,a=t.unknown.tooltip),{style:n,tip:a,text:i}}function n(t){var e=16,n=t,i="",a=t;return t.length>e+2&&(n=t.substring(0,e)+"...",i="simple-tip"),{style:i,tip:a,text:n}}function i(t){return a(x,t)}function a(t,e){var n,i;return e=e.toLowerCase(),null!=t[e]?(n=t[e].style,i=t[e].label):(n=t.other.style,i=e),{style:n,text:i}}function o(t){return r(A,t)}function r(t,e){var n="simple-tip",i=e,a="";return e=e.toLowerCase(),null!=t[e]&&(n=t[e].style,i=t[e].label,a=t[e].tooltip),{style:n,tip:a,text:i}}function l(t){return u(M,t)}function u(t,e){var n,i,a;return e=e.toLowerCase(),null!=t[e]?(n=t[e].style,i=t[e].label,a=t[e].tooltip):(n=t.unknown.style,i=t.unknown.label,a=t.unknown.tooltip),{style:n,tip:a,text:i}}function s(t,e){return c(I,t,e)}function c(t,e,n){var i="",a="",o="",r="";return e=e.toLowerCase(),null!=t[e]&&(r=t[e].tooltip,null!=n&&(r=n.toFixed(2)),i=t[e].label,a=t[e].style,o="oma_link"),{fisClass:a,omaClass:o,value:r,text:i}}function d(t,e,n,i){var a="NA",o=e+n,r="",l="";return t&&(r="mutation_table_allele_freq",a=t.toFixed(2),l=i),{text:a,total:o,style:r,tipClass:l}}function p(t){return h(t.pdbMatch)}function m(t){return h(t.igvLink)}function h(t){return t?"#":""}function f(t){var e="mutation-table-protein-change",n="click to highlight the position on the diagram",i="";return null!=t.aminoAcidChange&&t.aminoAcidChange.length>0&&"NA"!=t.aminoAcidChange&&-1!=t.cancerStudyShort.toLowerCase().indexOf("msk-impact")&&g(t.proteinChange,t.aminoAcidChange)&&(i="The original annotation file indicates a different value: "+v(t.aminoAcidChange)+""),{text:v(t.proteinChange),style:e,tip:n,additionalTip:i}}function g(t,e){var n=!1;if(t=v(t),e=v(e),e!==t){var i=t.match(/[A-Z]/g),a=e.match(/[A-Z]/g),o=t.match(/[0-9]+/),r=e.match(/[0-9]+/),l=t.match(/([a-z]+)/),u=e.match(/([a-z]+)/);o&&r&&o.length>0&&r.length>0&&o[0]!=r[0]?n=!0:i&&a&&i.length>0&&a.length>0&&"X"!==i[0]&&"X"!==a[0]&&i[0]!==a[0]?n=!0:i&&a&&i.length>1&&a.length>1&&i[1]!==a[1]?n=!0:l&&u&&l.length>0&&u.length>0&&l[0]!==u[0]&&(n=!0)}return n}function v(t){var e="p.";return-1!=t.indexOf(e)&&(t=t.substr(t.indexOf(e)+e.length)),t}function b(t){var e="tumor_type",n="";return{text:t.tumorType,style:e,tip:n}}function y(t){var e="",n="";return t>0&&(e="mutation_table_cosmic",n=t),{style:e,count:n}}function _(t){var e="",n="";return t>0&&(e="mutation_table_cbio_portal",n=t),{style:e,frequency:n}}function T(t){var e=t,n="mutation_table_int_value";return null==t&&(e="NA",n=""),{text:e,style:n}}function C(t){var e=t,n="mutation_table_allele_count";return null==t&&(e="NA",n=""),{text:e,style:n}}function P(t,e){var n;return t=t.toLowerCase(),n="low"==t||"l"==t?2:"medium"==t||"m"==t?3:"high"==t||"h"==t?4:"neutral"==t||"n"==t?1:-1,n>0&&!isNaN(e)&&(n+=e/1e3),n}function S(t){var e=parseInt(t);return isNaN(e)&&(e=-(1/0)),e}function w(t){var e=parseFloat(t);return isNaN(e)&&(e=-(1/0)),e}var D=MutationViewsUtil.getVisualStyleMaps(),x=D.mutationType,M=D.validationStatus,A=D.mutationStatus,I=D.omaScore,F=D.cna;return{getCaseId:n,getProteinChange:f,getPdbMatchLink:p,getIgvLink:m,getAlleleCount:C,getAlleleFreq:d,getCNA:t,getMutationType:i,getMutationStatus:o,getValidationStatus:l,getFis:s,getTumorType:b,getCosmic:y,getCbioPortal:_,getIntValue:T,assignValueToPredictedImpact:P,assignIntValue:S,assignFloatValue:w}}(),PileupUtil=function(){function t(t){for(var e=t.mutations,n={},i=0;i0&&(e[t[n].proteinChange]=t[n].proteinChange);var i=[];for(var a in e)i.push(a);i.sort();var o="";i.length>1&&(o=cbio.util.lcss(i[0],i[i.length-1]));for(var r=o,n=0;n0&&(e=t.numGermline/t.numCases*100,n+="Germline Mutation Rate: "+e.toFixed(1)+"%, "),e=t.numSomatic/t.numCases*100,n+="Somatic Mutation Rate: "+e.toFixed(1)+"%]"},this.countMutations=function(t,n){for(var i=n.length,o=0,r=0,l=0,u=0;u0})},this.containsRefAllele=function(t){return this._contains(t,function(t){return t.referenceAllele&&"NA"!=t.referenceAllele})},this.containsVarAllele=function(t){return this._contains(t,function(t){return t.variantAllele&&"NA"!=t.variantAllele})},this.containsEndPos=function(t){return this._contains(t,function(t){return t.endPos&&t.endPos>0})},this.containsFis=function(t){return this._contains(t,function(t){return t.functionalImpactScore&&"NA"!=t.functionalImpactScore})},this.containsCosmic=function(t){return this._contains(t,function(t){return t.cosmic&&t.cosmicCount&&t.cosmicCount>0})},this.containsMutationType=function(t){return this._contains(t,function(t){return t.mutationType&&"NA"!=t.mutationType})},this.containsMutationCount=function(t){return this._contains(t,function(t){return t.mutationCount&&t.mutationCount>0})},this.containsKeyword=function(t){return this._contains(t,function(t){return t.keyword&&"NA"!=t.keyword})},this.containsMutationEventId=function(t){return this._contains(t,function(t){return t.mutationEventId&&"NA"!=t.mutationEventId})},this.distinctTumorTypeCount=function(t){t=t.toUpperCase();var e=i[t],n={};if(null!=e)for(var a=0;a0?(i+=t[0].alignmentString,a=t[0].uniprotTo,e=t[0],_.each(t,function(t,n){var o=t.uniprotFrom-a-1,r=t.alignmentString;if(0==o)i+=r;else if(o>0){for(var l=[],u=0;o>u;u++)l.push(y);l.push(r),i+=l.join("")}else{var s=[],c=Math.min(-1*o,r.length);s.push(i.substr(i.length+o,c)),s.push(r.substr(0,c)),s[0]!=s[1]&&(console.log("[warning] alignment mismatch: "+e.alignmentId+" & "+t.alignmentId),console.log(s[0]),console.log(s[1])),i+=r.substr(-1*o)}a=Math.max(a,t.uniprotTo),a==t.uniprotTo&&(e=t)}),n.uniprotFrom=t[0].uniprotFrom,n.uniprotTo=n.uniprotFrom+i.length,n.pdbFrom=t[0].pdbFrom,n.mergedString=i,n.identityPerc=l(i),n.identity=u(i),n):n}function o(t,e){var n=null,i=t.getProteinStartPos(),a=t.mutationType.trim().toLowerCase();if(null==i||"fusion"==a)return n;for(var o=0;o=c.uniprotFrom&&i<=c.uniprotTo;if(d&&r(c,i)){n={pdbId:s.pdbId,chainId:s.chain.chainId};break}}if(n)break}return n}function r(t,e){var n=e-t.uniprotFrom,i=t.mergedString[n],a=i==y;return!a}function l(t){for(var e=0,n=0,i=0;i0){for(var a=!1,o=0;o0&&n[0].sort(function(t,e){return e.chain.mergedAlignment.mergedString.length-t.chain.mergedAlignment.mergedString.length}),n}function c(t,e){var n=!0;return(t.mergedAlignment.uniprotFrom>=e.mergedAlignment.uniprotTo||e.mergedAlignment.uniprotFrom>=t.mergedAlignment.uniprotTo)&&(n=!1),n}function d(t){var e=[];return t.each(function(t,n){t.chains.each(function(n,i){var a={pdbId:t.pdbId,chain:n};e.push(a)})}),p(e,[h,g,f,v,b]),e}function p(t,e){t.sort(function(t,n){for(var i=0,a=0;at.pdbId?-1:e.pdbIdt.chain.chainId?-1:e.chain.chainIdt)&&(t=this.getProteinChangeLocation()),t},getProteinChangeLocation:function(){var t=null,e=this.proteinChange,n=e.match(/[0-9]+/);return n&&n.length>0&&(t=n[0]),t},calcCosmicCount:function(t){var e=0;return t&&t.forEach(function(t){e+=t[2]}),e}}),MutationCollection=Backbone.Collection.extend({model:MutationModel,initialize:function(t){},parse:function(t){},url:function(){}}),PdbAlignmentModel=Backbone.Model.extend({initialize:function(t){this.alignmentId=t.alignmentId,this.pdbId=t.pdbId,this.chain=t.chain,this.uniprotId=t.uniprotId,this.pdbFrom=t.pdbFrom,this.pdbTo=t.pdbTo,this.uniprotFrom=t.uniprotFrom,this.uniprotTo=t.uniprotTo,this.alignmentString=t.alignmentString,this.eValue=t.eValue,this.identityPerc=t.identityPerc}}),PdbAlignmentCollection=Backbone.Collection.extend({model:PdbAlignmentModel,initialize:function(t){}}),PdbChainModel=Backbone.Model.extend({initialize:function(t){this.chainId=t.chainId,this.positionMap=t.positionMap,this.alignments=new PdbAlignmentCollection(t.alignments),this.mergedAlignment=PdbDataUtil.mergeAlignments(t.alignments)}}),PdbChainCollection=Backbone.Collection.extend({model:PdbChainModel,initialize:function(t){}}),PdbModel=Backbone.Model.extend({initialize:function(t){this.pdbId=t.pdbId,this.chains=new PdbChainCollection(t.chains)}}),PdbCollection=Backbone.Collection.extend({model:PdbModel,initialize:function(t){}}),Pileup=Backbone.Model.extend({initialize:function(t){this.pileupId=t.pileupId,this.mutations=t.mutations,this.count=t.count,this.location=t.location,this.label=t.label,this.stats=t.stats}}),CosmicTipView=Backbone.View.extend({render:function(){var t=this.compileTemplate();this.$el.html(t),this.format()},format:function(){this.$el.find(".cosmic-details-table").dataTable({aaSorting:[[2,"desc"]],sDom:"pt",aoColumnDefs:[{mRender:function(t,e,n){return''+t+""},aTargets:[0]},{sType:"aa-change-col",sClass:"left-align-td",aTargets:[1]},{sType:"numeric",sClass:"left-align-td",aTargets:[2]}],bDestroy:!1,bPaginate:!0,bJQueryUI:!0,bFilter:!1})},_parseCosmic:function(t){var e=[];return t.forEach(function(t){e.push(t[0]+""+t[1]+""+t[2])}),""+e.join("")+""},compileTemplate:function(){var t=this._parseCosmic(this.model.cosmic),e={cosmicDataRows:t,cosmicTotal:this.model.total,mutationKeyword:this.model.keyword},n=BackboneTemplateCache.getTemplateFn("mutation_details_cosmic_tip_template");return n(e)}}),LollipopTipStatsView=Backbone.View.extend({initialize:function(){},render:function(){var t=BackboneTemplateCache.getTemplateFn("mutation_details_lollipop_tip_stats_template"),e=this.$el.find("table tbody");return _.each(this.model,function(n){e.append(t(n))}),this}}),LollipopTipView=Backbone.View.extend({render:function(){var t=this.compileTemplate();this.$el.html(t),this.format()},format:function(){},showStats:!1,setShowStats:function(t){this.showStats=t},getShowStats:function(t){return this.showStats},compileTemplate:function(){var t=this.model,e=t.count>1?"mutations":"mutation",n={count:t.count,mutationStr:e,label:t.label},i=BackboneTemplateCache.getTemplateFn("mutation_details_lollipop_tip_template"),a=$(i(n)),o=a.find(".lollipop-stats");return this.showStats?(new LollipopTipStatsView({el:o,model:t.stats}).render(),o.find("table").dataTable({sDom:"t",bJQueryUI:!0,bDestroy:!0,aaSorting:[[1,"desc"]],aoColumns:[{bSortable:!1},{bSortable:!1}]})):o.hide(),a.html()}}),MainMutationView=Backbone.View.extend({initialize:function(t){this.options=t||{},this.dispatcher={},_.extend(this.dispatcher,Backbone.Events)},render:function(){var t=this,e={geneSymbol:t.model.geneSymbol,mutationSummary:t._mutationSummary(),uniprotId:t.model.sequence.metadata.identifier},n=BackboneTemplateCache.getTemplateFn("mutation_view_template"),i=n(e);t.$el.html(i),t.format()},format:function(){var t=this;t.$el.find(".mutation-details-filter-info").hide(),t.$el.find(".mutation-details-no-data-info").hide()},initComponents:function(t){var e=this,n=e.model.geneSymbol,i=e.model.mutationData,a=e.model.dataProxies,o=e.model.sequence,r=e.model.diagramOpts,l=e.model.tableOpts,u=e._initMutationDiagramView(n,i,o,a,r),s=u.mutationDiagram,c=null;s?t&&(c=e._init3dView(n,o,e.model.dataProxies.pdbProxy,t)):console.log("Error initializing mutation diagram: %s",n);var d=e._initMutationTableView(n,i,a,l);return e._mutationDiagram=s,e._tableView=d,e._mut3dView=c,{diagram:s,tableView:d,view3d:c}},initPdbPanelView:function(t){var e=this,n={el:e.$el.find(".mutation-pdb-panel-view"),model:{geneSymbol:e.model.geneSymbol,pdbColl:t,pdbProxy:e.model.dataProxies.pdbProxy},diagram:e._mutationDiagram},i=new PdbPanelView(n);return i.render(),e._pdbPanelView=i,i},_mutationSummary:function(){var t=this,e=t.model.dataProxies.mutationProxy.getMutationUtil(),n=t.model.geneSymbol,i=t.model.sampleArray,a="";if(i.length>0){var o=e.countMutations(n,i);a=e.generateSummary(o)}return a},_init3dView:function(t,e,n,i){var a=this,o=null;return i&&(o=new Mutation3dView({el:a.$el.find(".mutation-3d-initializer"),model:{uniprotId:e.metadata.identifier,geneSymbol:t,pdbProxy:n}}),o.render(),i.isVisible()&&o.resetView()),o},_initMutationDiagramView:function(t,e,n,i,a){var o=this,r={mutations:e,sequence:n,geneSymbol:t,dataProxies:i,diagramOpts:a},l=new MutationDiagramView({el:o.$el.find(".mutation-diagram-view"),model:r});return l.render(),l},_initMutationTableView:function(t,e,n,i){var a=this,o=new MutationDetailsTableView({el:a.$el.find(".mutation-table-container"),model:{geneSymbol:t,mutations:e,dataProxies:n,tableOpts:i}});return o.render(),o},addResetCallback:function(t){var e=this,n=e.$el.find(".mutation-details-filter-reset");n.click(t)},showFilterInfo:function(){this.$el.find(".mutation-details-filter-info").slideDown()},hideFilterInfo:function(){this.$el.find(".mutation-details-filter-info").slideUp()},showNoDataInfo:function(){this.$el.find(".mutation-details-no-data-info").slideDown()},hideNoDataInfo:function(){this.$el.find(".mutation-details-no-data-info").slideUp()}}),Mutation3dView=Backbone.View.extend({initialize:function(t){this.options=t||{},this.dispatcher={},_.extend(this.dispatcher,Backbone.Events)},render:function(){var t=this,e=(t.model.geneSymbol,BackboneTemplateCache.getTemplateFn("mutation_3d_view_template")),n=e({});this.$el.html(n),this.format()},format:function(){var t=this,e=t.$el.find(".mutation-3d-vis");e.attr("disabled","disabled");var n=function(n){if(n)e.removeAttr("disabled");else{var i=t.model.geneSymbol,a="No structure data for "+i,o={content:{text:a},hide:{fixed:!0,delay:100,event:"mouseout"},show:{event:"mouseover"},style:{classes:"qtip-light qtip-rounded qtip-shadow cc-ui-tooltip"},position:{my:"bottom center",at:"top center",viewport:$(window)}};t.$el.qtip(o)}},i=t.model.pdbProxy,a=t.model.uniprotId;i.hasPdbData(a,n)},addInitCallback:function(t){var e=this,n=e.$el.find(".mutation-3d-vis");n.click(t)},resetView:function(){var t=this,e=t.$el.find(".mutation-3d-vis");e.click()},isVisible:function(){var t=this;return t.$el.is(":visible")}}),Mutation3dVisInfoView=Backbone.View.extend({render:function(){var t=this,e=BackboneTemplateCache.getTemplateFn("mutation_3d_vis_info_template"),n=e(t.model);t.$el.html(n),t.format()},format:function(){var t=this,e=t.model.pdbInfo,n=t.model.molInfo;null==e||0==e.length?t.$el.find(".mutation-3d-pdb-info").hide():t._addExpander(".mutation-3d-pdb-info"),null==n||0==n.length?t.$el.find(".mutation-3d-mol-info").hide():t._addExpander(".mutation-3d-mol-info")},_addExpander:function(t){var e=this,n={slicePoint:40,widow:2,expandPrefix:" ",expandText:"[...]",userCollapseText:"[^]",moreClass:"expander-read-more",lessClass:"expander-read-less",detailClass:"expander-details",expandEffect:"fadeIn",collapseEffect:"fadeOut"};e.$el.find(t).expander(n)}}),Mutation3dVisView=Backbone.View.extend({initialize:function(t){this.options=t||{},this.dispatcher={},_.extend(this.dispatcher,Backbone.Events)},render:function(){var t=this,e=BackboneTemplateCache.getTemplateFn("mutation_3d_vis_template"),n=e({loaderImage:"images/ajax-loader.gif",helpImage:"images/help.png"});t.$el.html(n),t.format()},format:function(){var t=this,e=t.options.mut3dVis,n=t.$el;n.hide(),t.hideResidueWarning(),t.hideNoMapWarning();var i=t.$el.find(".mutation-3d-vis-help-content"),a=BackboneTemplateCache.getTemplateFn("3Dmol_basic_interaction");i.html(a({})),i.hide(),null!=e&&e.updateContainer(n),t.$el.find(".mutation-3d-close").click(function(){t.hideView()}),t.$el.find(".mutation-3d-minimize").click(function(){null!=e&&e.toggleSize()}),t._initMutationControls(),t._initProteinControls(),t._initButtons(),n.draggable({handle:".mutation-3d-info-title",stop:function(t,e){var i=parseInt(n.css("top")),a=parseInt(n.css("left"));0>i&&n.css("top",0),0>a&&n.css("left",0)}}),n.resizable({alsoResize:".mutation-3d-vis-container,.mutation-3d-vis-container div:eq(0)",handles:"sw, s, w",minWidth:400,minHeight:300,start:function(t,e){n.find(".mutation-3d-vis-help-content").css("width","auto"),n.css("position","fixed")},stop:function(t,e){n.css("height","auto"),n.css("position","fixed")},resize:function(t,n){t.stopPropagation(),e.resizeViewer()}}).on("resize",function(t){t.stopPropagation()})},_initButtons:function(){var t=this,e=t.options.mut3dVis,n=t.$el.find(".mutation-3d-vis-help-content"),i=t.$el.find(".mutation-3d-vis-help-init"),a=t.$el.find(".mutation-3d-vis-help-open"),o=t.$el.find(".mutation-3d-vis-help-close"),r=t.$el.find(".mutation-3d-pymol-dload");a.click(function(t){t.preventDefault(),n.slideToggle(),i.slideToggle()}),o.click(function(t){t.preventDefault(),n.slideToggle(),i.slideToggle()}),r.click(function(n){n.preventDefault();var i=e.generatePymolScript(),a=t.$el.find(".mutation-3d-pdb-id").text().trim()+"_"+t.$el.find(".mutation-3d-chain-id").text().trim()+".pml",o={filename:a,contentType:"text/plain;charset=utf-8",preProcess:!1};cbio.download.initDownload(i,o)}),r.qtip(t._generateTooltipOpts("Download PyMOL script"))},_initMutationControls:function(){var t=this,e=t.options.mut3dVis,n=t.$el.find(".mutation-3d-side-chain-select");n.change(function(){var t=$(this).val();e&&(e.updateOptions({displaySideChain:t}),e.reapplyStyle())});var i=t.$el.find(".mutation-3d-mutation-color-select");i.change(function(){var t=$(this).val();e&&(e.updateOptions({colorMutations:t}),e.reapplyStyle())}),t._initMutationColorInfo(),t._initSideChainInfo()},_initProteinControls:function(){var t=this,e=t.options.mut3dVis,n=t.$el.find(".mutation-3d-display-non-protein");n.change(function(){var t=n.is(":checked");e&&(e.updateOptions({restrictProtein:!t}),e.reapplyStyle())}),t._initHideNonProteinInfo(),t._initProteinSchemeSelector(),t._initProteinColorSelector()},_initProteinColorSelector:function(){var t=this,e=t.$el.find(".mutation-3d-protein-color-select"),n=t.options.mut3dVis;e.change(function(){var t=$(this).val();n.updateOptions({colorProteins:t}),n.reapplyStyle()})},_initProteinSchemeSelector:function(){var t=this,e=t.options.mut3dVis,n=t.$el.find(".mutation-3d-protein-style-select"),i=t.$el.find(".mutation-3d-protein-color-select");t._initProteinColorInfo(),n.change(function(){var t=$(this).val(),n=!1;i.find("option").removeAttr("disabled");var a=[];if("spaceFilling"==t?(a.push(i.find("option[value='bySecondaryStructure']")),a.push(i.find("option[value='byChain']"))):a.push(i.find("option[value='byAtomType']")),_.each(a,function(t,e){t.is(":selected")&&(t.removeAttr("selected"),i.find("option[value='uniform']").attr("selected","selected"),n="uniform"),t.attr("disabled","disabled")}),e){var o={};o.proteinScheme=t,n&&(o.colorProteins=n),e.updateOptions(o),e.reapplyStyle()}})},_initZoomSlider:function(){var t=this,e=t.$el.find(".mutation-3d-zoom-slider"),n=t.options.mut3dVis,i=function(t){return 0>t?100+t:100+5*t},a=function(t,e){n&&n.zoomTo(i(e.value))};e.slider({value:0,min:-80,max:80,stop:a,slide:a})},updateView:function(t,e,n){var i=this,a=i.options.mut3dVis,o=i.options.pdbProxy,r=function(t){n.positionMap=t,a.show(),i.refreshView(e,n),i.pdbId=e,i.chain=n},l=function(a){var l={pdbId:e,chainId:n.chainId,pdbInfo:"",molInfo:""};if(a&&a[e]){var u=PdbDataUtil.generatePdbInfoSummary(a[e],n.chainId);l.pdbInfo=u.title,l.molInfo=u.molecule}var s=new Mutation3dVisInfoView({el:i.$el.find(".mutation-3d-info"),model:l});s.render(),o.getPositionMap(t,n,r)};o.getPdbInfo(e,l)},refreshView:function(t,e){var n=this,i=n.options.mut3dVis;n.hideResidueWarning(),n.hideNoMapWarning();var a=function(t){0==t.length?n.showNoMapWarning():n.hideNoMapWarning()};if(null==t&&null==e||t==n.pdbId&&e==n.chain){var o=i.refresh();a(o),n.dispatcher.trigger(MutationDetailsEvents.VIEW_3D_STRUCTURE_RELOADED)}else n.showLoader(),setTimeout(function(){var o=i.reload(t,e,function(){n.hideLoader(),n.dispatcher.trigger(MutationDetailsEvents.VIEW_3D_STRUCTURE_RELOADED)});a(o)},50)},_initMutationColorInfo:function(){var t=this,e=t.$el.find(".mutation-type-color-help"),n=BackboneTemplateCache.getTemplateFn("mutation_3d_type_color_tip_template"),i=n({}),a=t._generateTooltipOpts(i);a.style.classes+=" qtip-wide",e.qtip(a)},_initProteinColorInfo:function(){var t=this,e=t.$el.find(".protein-struct-color-help"),n=BackboneTemplateCache.getTemplateFn("mutation_3d_structure_color_tip_template"),i=n({}),a=t._generateTooltipOpts(i);a.style.classes+=" qtip-wide",e.qtip(a)},_initSideChainInfo:function(){var t=this,e=t.$el.find(".display-side-chain-help"),n=BackboneTemplateCache.getTemplateFn("mutation_3d_side_chain_tip_template"),i=n({}),a=t._generateTooltipOpts(i);e.qtip(a)},_initHideNonProteinInfo:function(){var t=this,e=t.$el.find(".display-non-protein-help"),n=BackboneTemplateCache.getTemplateFn("mutation_3d_non_protein_tip_template"),i=n({}),a=t._generateTooltipOpts(i);e.qtip(a)},_generateTooltipOpts:function(t){return{content:{text:t},hide:{fixed:!0,delay:100,event:"mouseout"},show:{event:"mouseover"},style:{classes:"qtip-light qtip-rounded qtip-shadow"},position:{my:"top right",at:"bottom center",viewport:$(window)}}},minimizeView:function(){var t=this,e=t.options.mut3dVis;e&&e.minimize()},maximizeView:function(){var t=this,e=t.options.mut3dVis;e&&e.maximize()},resetPanelPosition:function(){var t=this,e=t.$el;e.css({left:"",position:"",top:0})},hideView:function(){var t=this,e=t.options.mut3dVis;null!=e&&e.hide(),t.dispatcher.trigger(MutationDetailsEvents.VIEW_3D_PANEL_CLOSED)},isVisible:function(){var t=this,e=t.options.mut3dVis;return e.isVisible()},focusView:function(t){var e=this,n=e.options.mut3dVis;return t?n.focusOn(t):(n.resetFocus(),!0)},highlightView:function(t,e){var n=this,i=n.options.mut3dVis;return i.highlight(t,e)},resetHighlight:function(){var t=this,e=t.options.mut3dVis;e.resetHighlight()},showLoader:function(){var t=this,e=t.$el.find(".mutation-3d-vis-loader"),n=t.$el.find(".mutation-3d-vis-container"),i=n.css("height");0!==i&&"0px"!==i&&(t._actualHeight=i,n.css("height",0)),e.show()},hideLoader:function(){var t=this,e=t.$el.find(".mutation-3d-vis-loader"),n=t.$el.find(".mutation-3d-vis-container");e.hide(),n.css("height",t._actualHeight)},showResidueWarning:function(t,e){var n=this,i=n.$el.find(".mutation-3d-residue-warning"),a=n.$el.find(".mutation-3d-unmapped-info");n.$el.find(".mutation-3d-nomap-warning").is(":visible")||(e>1?a.text(t+" of the selections"):a.text("Selected mutation"),i.show())},hideResidueWarning:function(){var t=this,e=t.$el.find(".mutation-3d-residue-warning");e.hide()},showNoMapWarning:function(){var t=this,e=t.$el.find(".mutation-3d-nomap-warning");e.show()},hideNoMapWarning:function(){var t=this,e=t.$el.find(".mutation-3d-nomap-warning");e.hide()}}),MutationCustomizePanelView=Backbone.View.extend({initialize:function(t){this.options=t||{}},render:function(){var t=this,e=t.options.diagram,n={minY:2,maxY:e.getMaxY()},i=BackboneTemplateCache.getTemplateFn("mutation_customize_panel_template"),a=i(n);t.$el.html(a),t.format()},format:function(){var t=this,e=t.options.diagram;t.$el.hide();var n=t.$el.find(".diagram-customize-close"),i=t.$el.find(".diagram-y-axis-slider"),a=t.$el.find(".diagram-y-axis-limit-input");n.click(function(e){e.preventDefault(),t.toggleView()});var o=e.getMaxY();a.val(o),i.slider({value:o,min:2,max:o,change:function(t,n){a.val(n.value),e.updateOptions({maxLengthY:n.value}),e.rescaleYAxis()},slide:function(t,e){a.val(e.value)}}),a.keypress(function(t){var n=13;if(t.keyCode==n){var r=a.val();isNaN(r)||r>o||2>r?a.val(e.getMaxY()):i.slider("option","value",Math.floor(r))}})},toggleView:function(){var t=this;t.$el.slideToggle()}}),MutationDetailsTableView=Backbone.View.extend({initialize:function(t){this.options=t||{},this.dispatcher={},_.extend(this.dispatcher,Backbone.Events)},render:function(){var t=this,e=BackboneTemplateCache.getTemplateFn("mutation_details_table_template"),n=e({loaderImage:"images/ajax-loader.gif"});t.$el.html(n),t._initMutationTable(),t.format()},_initMutationTable:function(t){var e=this,n=jQuery.extend(!0,{},e.model.tableOpts);n.el=n.el||e.$el.find(".mutation_details_table");var i=new MutationCollection(e.model.mutations),a=new MutationDetailsUtil(i),o=new MutationDetailsTable(n,e.model.geneSymbol,a,e.model.dataProxies);return e.tableUtil=o,_.isFunction(t)&&t(e,o),e._generateRowData(o.getColumnOptions(),i,function(t){o.renderTable(t)}),o},_generateRowData:function(t,e,n){var i=[];e.each(function(e){for(var n={mutation:e},a=[n],o=0;o<_.size(t)-1;o++)a.push(null);i.push(a)}),n(i)},format:function(){},hideView:function(){var t=this;t.$el.hide()},showView:function(){var t=this;t.$el.show()},highlight:function(t){for(var e=this,n=e.$el.find(".mutation_details_table"),i=0;i0)&&(i.pdbInfo=": "+e),(null!=n||n.length>0)&&(i.molInfo=": "+n);var a=BackboneTemplateCache.getTemplateFn("mutation_details_pdb_chain_tip_template");return a(i)}}),PdbPanelView=Backbone.View.extend({initialize:function(t){this.options=t||{},this.collapseTimer=null,this.expandTimer=null},render:function(){var t=this,e=BackboneTemplateCache.getTemplateFn("pdb_panel_view_template"),n=e({});t.$el.html(n),t.pdbPanel=t._initPdbPanel(),t.format()},format:function(){var t=this;t.$el.hide();var e=t.$el.find(".expand-collapse-pdb-panel"),n=t.$el.find(".init-pdb-table"),i=t.$el.find(".pdb-table-controls"),a=t.$el.find(".triangle-down"),o=t.$el.find(".triangle");t.pdbPanel.hasMoreChains()&&(e.button({icons:{primary:"ui-icon-triangle-2-n-s"},text:!1}),e.css({width:"300px",height:"12px"}),e.click(function(){t.pdbPanel.toggleHeight()})),e.hide(),i.hide(),a.hide(),o.click(function(t){n.click()}),t.$el.find(".mutation-pdb-main-container").mouseenter(function(e){t.autoExpand()}),t.$el.find(".mutation-pdb-main-container").mouseleave(function(e){t.autoCollapse()})},hideView:function(){var t=this;t.$el.slideUp()},showView:function(){var t=this;t.$el.slideDown()},initPdbTableView:function(t,e){var n=this,i={el:n.$el.find(".mutation-pdb-table-view"),model:{geneSymbol:n.model.geneSymbol,pdbColl:t,pdbProxy:n.model.pdbProxy}},a=new PdbTableView(i);return n.pdbTableView=a,a.render(e),a},addInitCallback:function(t){var e=this,n=e.$el.find(".init-pdb-table");n.click(function(e){e.preventDefault(),t(e)})},toggleTableControls:function(){var t=this;t.$el.find(".triangle").toggle()},selectDefaultChain:function(){var t=this,e=t.pdbPanel,n=e.getDefaultChainGroup();t.clearTimers(),e.restoreChainPositions(function(){e.highlight(n)})},selectChain:function(t,e){var n=this,i=n.pdbPanel;n.clearTimers(),i.restoreChainPositions(function(){i.expandToChainLevel(t,e);var n=i.getChainGroup(t,e);n&&i.highlight(n)})},getSelectedChain:function(){var t=this,e=t.pdbPanel;return e.getHighlighted()},autoCollapse:function(t){null==t&&(t=2e3);var e=this,n=e.$el.find(".expand-collapse-pdb-panel"),i=e.$el.find(".pdb-table-controls"),a=e.$el.find(".pdb-table-wrapper");e.clearTimers(),e.collapseTimer=setTimeout(function(){e.pdbPanel.minimizeToHighlighted(),n.slideUp(),i.slideUp(),a.slideUp()},t)},autoExpand:function(t){null==t&&(t=400);var e=this,n=e.$el.find(".expand-collapse-pdb-panel"),i=e.$el.find(".pdb-table-controls"),a=e.$el.find(".pdb-table-wrapper");e.clearTimers(),e.expandTimer=setTimeout(function(){e.pdbPanel.restoreToFull(),e.pdbPanel.hasMoreChains()&&n.slideDown(),i.slideDown(),a.slideDown(),null!=e.pdbTableView&&e.pdbTableView.refreshView()},t)},toggleScrollBar:function(t){var e=this,n=e.$el.find(".mutation-pdb-panel-container");t>0?(n.css("max-height",t),n.css("overflow",""),n.css("overflow-y","scroll")):(n.css("max-height",""),n.css("overflow-y",""),n.css("overflow","hidden"))},scrollToSelected:function(){var t=this,e=t.$el.find(".mutation-pdb-panel-container");e.scrollTo($(".pdb-selection-rectangle-group"),{axis:"y",duration:800,offset:-150})},clearTimers:function(){var t=this;null!=t.collapseTimer&&clearTimeout(t.collapseTimer),null!=t.expandTimer&&clearTimeout(t.expandTimer)},_initPdbPanel:function(){var t=this,e=null,n=t.model.pdbColl,i=t.model.pdbProxy,a=t.options.diagram;if(null!=a){var o=a.xScale,r={el:t.$el.find(".mutation-pdb-panel-container"),marginLeft:a.options.marginLeft,marginRight:a.options.marginRight,maxHeight:200};e=new MutationPdbPanel(r,n,i,o),e.init()}return e}}),PdbTableView=Backbone.View.extend({initialize:function(t){this.options=t||{}},render:function(t){var e=this,n=BackboneTemplateCache.getTemplateFn("pdb_table_view_template"),i=n({loaderImage:"images/ajax-loader.gif"});e.$el.html(i),e._initPdbTable(t),e.format()},format:function(){var t=this;t.$el.hide()},hideView:function(){var t=this;t.$el.slideUp()},showView:function(){var t=this;t.$el.slideDown(); -},toggleView:function(){var t=this;t.$el.slideToggle()},refreshView:function(){var t=this;t.pdbTable.getDataTable().fnAdjustColumnSizing()},resetFilters:function(){var t=this;t.pdbTable.cleanFilters()},selectChain:function(t,e){var n=this;null!=n.pdbTable&&n.pdbTable.selectRow(t,e)},scrollToSelected:function(){var t=this,e=t.pdbTable.getSelectedRow(),n=t.$el.find(".dataTables_scrollBody");n.scrollTo($(e),{axis:"y",duration:800})},_initPdbTable:function(t){var e=this,n=e.model.pdbColl,i=e.model.pdbProxy,a=jQuery.extend(!0,{},e.model.tableOpts);a.el=a.el||e.$el.find(".pdb-chain-table");var o=new MutationPdbTable(a);return e.pdbTable=o,_.isFunction(t)&&t(e,o),e._generateRowData(o.getColumnOptions(),n,i,function(t){o.renderTable(t),e.$el.find(".pdb-chain-table-loader").hide()}),o},_generateRowData:function(t,e,n,i){var a=[],o=[];e.each(function(t){o.push(t.pdbId)}),n.getPdbInfo(o.join(" "),function(n){e.each(function(e){e.chains.each(function(i){for(var o={pdbId:e.pdbId,chain:i,organism:PdbDataUtil.getOrganism(n[e.pdbId],i.chainId),summary:PdbDataUtil.generatePdbInfoSummary(n[e.pdbId],i.chainId)},r=[o],l=0;l<_.size(t)-1;l++)r.push(null);a.push(r)})}),i(a)})}}),PredictedImpactTipView=Backbone.View.extend({render:function(){var t=this.compileTemplate();this.$el.html(t),this.format()},format:function(){var t=function(t){var e=!0;return(null==t||"NA"==t||0==t.length)&&(e=!1),e},e=this.model.xvia;t(e)||this.$el.find(".mutation-assessor-main-link").hide();var n=this.model.pdbLink;t(n)||this.$el.find(".mutation-assessor-3d-link").hide();var i=this.model.msaLink;t(i)||this.$el.find(".mutation-assessor-msa-link").hide()},compileTemplate:function(){var t={linkOut:this.model.xvia,msaLink:this.model.msaLink,pdbLink:this.model.pdbLink,impact:this.model.impact},e=BackboneTemplateCache.getTemplateFn("mutation_details_fis_tip_template");return e(t)}}),RegionTipView=Backbone.View.extend({render:function(){var t=this.compileTemplate();this.$el.html(t),this.format()},format:function(){},compileTemplate:function(){var t={identifier:this.model.identifier,type:this.model.type.toLowerCase(),description:this.model.description,start:this.model.start,end:this.model.end,pfamAccession:this.model.pfamAccession,mutationAlignerInfo:this.model.mutationAlignerInfo},e=BackboneTemplateCache.getTemplateFn("mutation_details_region_tip_template");return e(t)}});MutationAlignerDataProxy.prototype=new AbstractDataProxy,MutationAlignerDataProxy.prototype.constructor=MutationAlignerDataProxy,MutationDataProxy.prototype=new AbstractDataProxy,MutationDataProxy.prototype.constructor=MutationDataProxy,PancanMutationDataProxy.prototype=new AbstractDataProxy,PancanMutationDataProxy.prototype.constructor=PancanMutationDataProxy,PdbDataProxy.prototype=new AbstractDataProxy,PdbDataProxy.prototype.constructor=PdbDataProxy,PfamDataProxy.prototype=new AbstractDataProxy,PfamDataProxy.prototype.constructor=PfamDataProxy,PortalDataProxy.prototype=new AbstractDataProxy,PortalDataProxy.prototype.constructor=PortalDataProxy,MutationDetailsTable.prototype=new AdvancedDataTable,MutationDetailsTable.prototype.constructor=MutationDetailsTable,MutationDiagram.prototype.defaultOpts={el:"#mutation_diagram_d3",elWidth:740,elHeight:180,marginLeft:45,marginRight:30,marginTop:30,marginBottom:60,labelTop:"",labelTopFont:"sans-serif",labelTopFontColor:"#2E3436",labelTopFontSize:"12px",labelTopFontWeight:"bold",labelTopMargin:2,labelX:!1,labelXFont:"sans-serif",labelXFontColor:"#2E3436",labelXFontSize:"12px",labelXFontWeight:"normal",labelY:"# Mutations",labelYFont:"sans-serif",labelYFontColor:"#2E3436",labelYFontSize:"12px",labelYFontWeight:"normal",minLengthX:0,minLengthY:5,maxLengthX:1/0,maxLengthY:1/0,seqFillColor:"#BABDB6",seqHeight:14,seqPadding:5,regionHeight:24,regionFont:"sans-serif",regionFontColor:"#FFFFFF",regionFontSize:"12px",regionTextAnchor:"middle",showRegionText:!0,showStats:!1,multiSelectKeycode:16,lollipopLabelCount:1,lollipopLabelThreshold:2,lollipopFont:"sans-serif",lollipopFontColor:"#2E3436",lollipopFontSize:"10px",lollipopTextAnchor:"auto",lollipopTextPadding:8,lollipopTextAngle:0,lollipopFillColor:{missense_mutation:"#008000",nonsense_mutation:"#FF0000",nonstop_mutation:"#FF0000",frame_shift_del:"#FF0000",frame_shift_ins:"#FF0000",in_frame_ins:"#000000",in_frame_del:"#000000",splice_site:"#FF0000",other:"#808080","default":"#800080"},lollipopBorderColor:"#BABDB6",lollipopBorderWidth:.5,lollipopSize:30,lollipopHighlightSize:100,lollipopStrokeWidth:1,lollipopStrokeColor:"#BABDB6",lollipopShapeRegular:"circle",lollipopShapeSpecial:"circle",xAxisPadding:10,xAxisTickIntervals:[100,200,400,500,1e3,2e3,5e3,1e4,2e4,5e4],xAxisTicks:8,xAxisTickSize:6,xAxisStroke:"#AAAAAA",xAxisFont:"sans-serif",xAxisFontSize:"10px",xAxisFontColor:"#2E3436",yAxisPadding:5,yAxisLabelPadding:15,yAxisTicks:10,yAxisTickIntervals:[1,2,5,10,20,50,100,200,500],yAxisTickSize:6,yAxisStroke:"#AAAAAA",yAxisFont:"sans-serif",yAxisFontSize:"10px",yAxisFontColor:"#2E3436",animationDuration:1e3,fadeDuration:1500,lollipopTipFn:function(t,e,n){var i=new LollipopTipView({model:e});i.setShowStats(n);var a=i.compileTemplate(),o={content:{text:a},hide:{fixed:!0,delay:100,event:"mouseout"},show:{event:"mouseover"},style:{classes:"qtip-light qtip-rounded qtip-shadow cc-ui-tooltip"},position:{my:"bottom left",at:"top center",viewport:$(window)}};cbio.util.addTargetedQTip(t,o,"mouseover")},regionTipFn:function(t,e,n){var i={identifier:e.metadata.identifier,type:e.type,description:e.metadata.description,start:e.metadata.start,end:e.metadata.end,pfamAccession:e.metadata.accession,mutationAlignerInfo:""};n.getMutationAlignerData({pfamAccession:e.metadata.accession},function(e){if(null!=e&&null!=e.linkToMutationAligner&&e.linkToMutationAligner.length>0){var n=BackboneTemplateCache.getTemplateFn("mutation_aligner_info_template");i.mutationAlignerInfo=n({linkToMutationAligner:e.linkToMutationAligner})}var a=new RegionTipView({model:i}),o=a.compileTemplate(),r={content:{text:o},hide:{fixed:!0,delay:100,event:"mouseout"},show:{event:"mouseover"},style:{classes:"qtip-light qtip-rounded qtip-shadow qtip-lightyellow"},position:{my:"bottom left",at:"top center",viewport:$(window)}};cbio.util.addTargetedQTip(t,r)})}},MutationDiagram.prototype.updateOptions=function(t){var e=this;e.options=jQuery.extend(!0,{},e.options,t);var n=e.xMax=e.calcXMax(e.options,e.data),i=e.maxCount=e.calcMaxCount(e.data.pileups),a=e.yMax=e.calcYMax(e.options,i);e.bounds=this.calcBounds(e.options),e.xScale=this.xScaleFn(e.bounds,n),e.yScale=this.yScaleFn(e.bounds,a)},MutationDiagram.prototype.rescaleYAxis=function(){var t=this,e=t.maxCount=t.calcMaxCount(t.data.pileups),n=t.calcYMax(t.options,e);t.svg.select(".mut-dia-y-axis").remove(),t.drawYAxis(t.svg,t.yScale,n,t.options,t.bounds),t.updatePlot()},MutationDiagram.prototype.updateSequenceData=function(t){var e=this;e.data.sequence=t},MutationDiagram.prototype.initDiagram=function(){var t=this,e=$(t.options.el)[0],n=d3.select(e),i=t.bounds=t.calcBounds(t.options);t.mutationPileupMap=PileupUtil.mapToMutations(t.data.pileups);var a=t.createSvg(n,t.options.elWidth,t.options.elHeight);t.svg=a,t.drawDiagram(a,i,t.options,t.data),t.addDefaultListeners()},MutationDiagram.prototype.calcBounds=function(t){var e={};return e.width=t.elWidth-(t.marginLeft+t.marginRight),e.height=t.elHeight-(t.marginBottom+t.marginTop),e.x=t.marginLeft,e.y=t.elHeight-t.marginBottom,e},MutationDiagram.prototype.drawDiagram=function(t,e,n,i){var a=this,o=(parseInt(i.sequence.length),a.maxCount=a.calcMaxCount(i.pileups)),r=a.xMax=a.calcXMax(n,i),l=a.yMax=a.calcYMax(n,o),u=i.sequence.regions,s=i.pileups,c=a.generateSequenceTooltip(i),d=a.xScale=a.xScaleFn(e,r),p=a.yScale=a.yScaleFn(e,l);a.drawXAxis(t,d,r,n,e),0!=n.labelX,a.drawYAxis(t,p,l,n,e),0!=n.labelY&&(a.yAxisLabel=a.drawYAxisLabel(t,n,e)),0!=n.topLabel&&(a.topLabel=a.drawTopLabel(t,n,e));t.append("rect").attr("fill","#FFFFFF").attr("opacity",0).attr("x",e.x).attr("y",e.y-e.height).attr("width",e.width).attr("height",e.height).attr("class","mut-dia-background");a.drawPlot(t,s,n,e,d,p);var m=a.drawSequence(t,n,e);m.attr("title",c);for(var h=0,f=u.length;f>h;h++)a.drawRegion(t,u[h],n,e,d)},MutationDiagram.prototype.xScaleFn=function(t,e){return d3.scale.linear().domain([0,e]).range([t.x,t.x+t.width])},MutationDiagram.prototype.yScaleFn=function(t,e){return d3.scale.linear().domain([0,e]).range([t.y,t.y-t.height])},MutationDiagram.prototype.calcXMax=function(t,e){var n=parseInt(e.sequence.length);return Math.min(t.maxLengthX,Math.max(n,t.minLengthX))},MutationDiagram.prototype.calcYMax=function(t,e){return Math.min(t.maxLengthY,Math.max(e,t.minLengthY))},MutationDiagram.prototype.generateSequenceTooltip=function(t){var e="",n=parseInt(t.sequence.length);return t.sequence.metadata.identifier&&(e+=t.sequence.metadata.identifier,t.sequence.metadata.description&&(e+=", "+t.sequence.metadata.description)),e+=" ("+n+"aa)"},MutationDiagram.prototype.drawPlot=function(t,e,n,i,a,o){var r=this,l=r.gLabel;null===l&&(l=t.append("g").attr("class","mut-dia-lollipop-labels"),r.gLabel=l);var u=r.gLine;null===u&&(u=t.append("g").attr("class","mut-dia-lollipop-lines"),r.gLine=u);var s=r.gData;null===s&&(s=t.append("g").attr("class","mut-dia-lollipop-points"),r.gData=s);for(var c=0;co)break}return i},MutationDiagram.prototype.getTickValues=function(t,e){for(var n=[],i=0;t>i;)n.push(i),i+=e/2;return n.push(t),n},MutationDiagram.prototype.drawXAxis=function(t,e,n,i,a){var o=this,r=o.calcTickInterval(i.xAxisTickIntervals,n,i.xAxisTicks),l=o.getTickValues(n,r),u=function(t){return t==n?t+" aa":t%r!=0?"":n-t>r/3?t:""},s=i.xAxisTickSize,c=d3.svg.axis().scale(e).orient("bottom").tickValues(l).tickFormat(u).tickSize(s,s/2,0),d=a.y+i.regionHeight+i.xAxisPadding,p=t.append("g").attr("class","mut-dia-x-axis").attr("transform","translate(0,"+d+")").call(c);return o.formatAxis(".mut-dia-x-axis",i.xAxisStroke,i.xAxisFont,i.xAxisFontSize,i.xAxisFontColor),p},MutationDiagram.prototype.drawYAxis=function(t,e,n,i,a){var o=this,r=o.calcTickInterval(i.yAxisTickIntervals,n,i.yAxisTicks),l=o.getTickValues(n,2*r),u=function(t){var e="";return t==n?(e=t,o.maxCount>n&&(e=">"+t)):0==t&&(e=t),e},s=i.yAxisTickSize,c=d3.svg.axis().scale(e).orient("left").tickValues(l).tickFormat(u).tickSize(s,s/2,0),d=a.x-i.yAxisPadding,p=t.append("g").attr("class","mut-dia-y-axis").attr("transform","translate("+d+",0)").call(c);return o.formatAxis(".mut-dia-y-axis",i.yAxisStroke,i.yAxisFont,i.yAxisFontSize,i.yAxisFontColor),p},MutationDiagram.prototype.drawTopLabel=function(t,e,n){var i=e.labelTopMargin,a=e.marginTop/2,o=t.append("text").attr("fill",e.labelTopFontColor).attr("text-anchor","start").attr("x",i).attr("y",a).attr("class","mut-dia-top-label").style("font-family",e.labelTopFont).style("font-size",e.labelTopFontSize).style("font-weight",e.labelTopFontWeight).text(e.labelTop);return o},MutationDiagram.prototype.drawYAxisLabel=function(t,e,n){var i=n.x-e.yAxisPadding-e.yAxisTickSize-e.yAxisLabelPadding,a=n.y-n.height/2,o=t.append("text").attr("fill",e.labelYFontColor).attr("text-anchor","middle").attr("x",i).attr("y",a).attr("class","mut-dia-y-axis-label").attr("transform","rotate(270, "+i+","+a+")").style("font-family",e.labelYFont).style("font-size",e.labelYFontSize).style("font-weight",e.labelYFontWeight).text(e.labelY);return o},MutationDiagram.prototype.formatAxis=function(t,e,n,i,a){var o=d3.selectAll(t+" line");o.style("fill","none").style("stroke",e).style("shape-rendering","crispEdges"),o=d3.selectAll(t+" path"),o.style("fill","none").style("stroke",e).style("shape-rendering","crispEdges"),o=d3.selectAll(t+" text"),o.attr("fill",a).style("font-family",n).style("font-size",i)},MutationDiagram.prototype.drawLollipop=function(t,e,n,i,a,o,r){var l=this,u=i.lollipopShapeRegular,s=n.count,c=n.location,d=o(c),p=r(s);s>i.maxLengthY&&(u=i.lollipopShapeSpecial,p=r(i.maxLengthY));var m=l.getLollipopFillColor(i,n);l.updateColorMap(n,m);var h=t.append("path").attr("d",d3.svg.symbol().size(i.lollipopSize).type(u)).attr("transform","translate("+d+","+p+")").attr("fill",m).attr("stroke",i.lollipopBorderColor).attr("stroke-width",i.lollipopBorderWidth).attr("id",n.pileupId).attr("class","mut-dia-data-point").attr("opacity",0);l.fadeIn(h),h.datum(n);var f=i.lollipopTipFn;f(h,n,i.showStats);var g=e.append("line").attr("x1",d).attr("y1",p).attr("x2",d).attr("y2",l.calcSequenceBounds(a,i).y).attr("stroke",i.lollipopStrokeColor).attr("stroke-width",i.lollipopStrokeWidth).attr("class","mut-dia-data-line").attr("opacity",0);return l.fadeIn(g),{dataPoint:h,line:g}},MutationDiagram.prototype.updateColorMap=function(t,e){for(var n=this,i=0;it.options.maxLengthY&&(n=t.options.lollipopShapeSpecial),n};return e},MutationDiagram.prototype.getLollipopFillColor=function(t,e){var n,i=t.lollipopFillColor;if(_.isFunction(i))n=i();else if("string"==typeof i)n=i;else{var a=PileupUtil.getMutationTypeArray(e);if(a.length>1&&a[0].count==a[1].count){var o=PileupUtil.getMutationTypeGroups(e);n=1==o.length?i[a[0].type]:i["default"]}else n=void 0==i[a[0].type]?i.other:i[a[0].type]}return n},MutationDiagram.prototype.drawLollipopLabels=function(t,e,n,i,a){var o=this,r=function(t,e){var i=e;if("auto"==i.toLowerCase()){var a=t.attr("x")-t.node().getComputedTextLength()/2;i=a1){for(var s=e[0].count,c=0;cl&&c>u&&(l=0)}for(var d=0;l>d&&d1&&e[d].counti&&(t=t.substring(0,3)+"..",r.text(t),r.node().getComputedTextLength()>i&&(r.remove(),r=null)),r},MutationDiagram.prototype.drawSequence=function(t,e,n){var i=this.calcSequenceBounds(n,e);return t.append("rect").attr("fill",e.seqFillColor).attr("x",i.x).attr("y",i.y).attr("width",i.width).attr("height",i.height).attr("class","mut-dia-sequence")},MutationDiagram.prototype.calcMaxCount=function(t){var e=-1;return t.length>0&&(e=t[0].count),e},MutationDiagram.prototype.calcSequenceBounds=function(t,e){var n=t.x,i=t.y+Math.abs(e.regionHeight-e.seqHeight)/2+e.seqPadding,a=t.width,o=e.seqHeight;return{x:n,y:i,width:a,height:o}},MutationDiagram.prototype.updatePlot=function(t){var e=this,n=e.pileups;t&&(e.pileups=n=t,e.mutationPileupMap=PileupUtil.mapToMutations(n)),e.cleanPlotArea(),e.mutationColorMap={},e.drawPlot(e.svg,n,e.options,e.bounds,e.xScale,e.yScale);for(var i in e.listeners){var a=e.svg.selectAll(i);for(var o in e.listeners[i])a.on(o,e.listeners[i][o])}return e.highlighted={},e.dispatcher.trigger(MutationDetailsEvents.DIAGRAM_PLOT_UPDATED),e.isFiltered()},MutationDiagram.prototype.cleanPlotArea=function(){var t=this,e=t.gLabel.selectAll("text"),n=t.gLine.selectAll("line"),i=t.gData.selectAll(".mut-dia-data-point");t.fadeOut(e,function(t){$(t).remove()}),t.fadeOut(n,function(t){$(t).remove()}),t.fadeOut(i,function(t){$(t).remove()})},MutationDiagram.prototype.resetPlot=function(){var t=this;t.updatePlot(t.data.pileups),t.dispatcher.trigger(MutationDetailsEvents.DIAGRAM_PLOT_RESET)},MutationDiagram.prototype.updateTopLabel=function(t){var e=this;(void 0==t||null==t)&&(t=""),e.topLabel.text(t)},MutationDiagram.prototype.addListener=function(t,e,n){var i=this;i.svg.selectAll(t).on(e,n),null==i.listeners[t]&&(i.listeners[t]={}),i.listeners[t][e]=n},MutationDiagram.prototype.removeListener=function(t,e){var n=this;n.svg.selectAll(t).on(e,null),n.listeners[t]&&n.listeners[t][e]&&delete n.listeners[t][e]},MutationDiagram.prototype.addDefaultListeners=function(){var t=this;t.addListener(".mut-dia-background","click",function(e,n){var i=!t.isHighlighted()||t.multiSelect;i||(t.clearHighlights(),t.dispatcher.trigger(MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED))}),t.addListener(".mut-dia-data-point","click",function(e,n){t.isHighlighted(this)?(t.removeHighlight(this),t.multiSelect||t.clearHighlights(),t.dispatcher.trigger(MutationDetailsEvents.LOLLIPOP_DESELECTED,e,n)):(t.multiSelect||t.clearHighlights(),t.highlight(this),t.dispatcher.trigger(MutationDetailsEvents.LOLLIPOP_SELECTED,e,n))}),t.addListener(".mut-dia-data-point","mouseout",function(e,n){t.dispatcher.trigger(MutationDetailsEvents.LOLLIPOP_MOUSEOUT,e,n)}),t.addListener(".mut-dia-data-point","mouseover",function(e,n){t.dispatcher.trigger(MutationDetailsEvents.LOLLIPOP_MOUSEOVER,e,n)});var e=function(e,n){t.multiSelect&&d3.event.preventDefault()};t.addListener(".mut-dia-data-point","mousedown",e),t.addListener(".mut-dia-background","mousedown",e),$(window).on("keydown",function(e){e.keyCode==t.options.multiSelectKeycode&&(t.multiSelect=!0)}),$(window).on("keyup",function(e){e.keyCode==t.options.multiSelectKeycode&&(t.multiSelect=!1)})},MutationDiagram.prototype.isHighlighted=function(t){var e=this,n=!1;if(void 0==t)n=!_.isEmpty(e.highlighted);else{var i=d3.select(t),a=i.datum().location;void 0!=e.highlighted[a]&&(n=!0)}return n},MutationDiagram.prototype.clearHighlights=function(){var t=this,e=t.gData.selectAll(".mut-dia-data-point");e.transition().ease("elastic").duration(t.options.animationDuration).attr("d",d3.svg.symbol().size(t.options.lollipopSize).type(t.getLollipopShapeFn())),t.highlighted={}},MutationDiagram.prototype.highlightMutation=function(t){var e=this,n=e.mutationPileupMap[t],i=e.svg.select("#"+n);i.length>0&&e.highlight(i[0][0])},MutationDiagram.prototype.highlight=function(t){var e=this,n=d3.select(t);n.transition().ease("elastic").duration(e.options.animationDuration).attr("d",d3.svg.symbol().size(e.options.lollipopHighlightSize).type(e.getLollipopShapeFn()));var i=n.datum().location;e.highlighted[i]=n},MutationDiagram.prototype.removeHighlight=function(t){var e=this,n=d3.select(t);n.transition().ease("elastic").duration(e.options.animationDuration).attr("d",d3.svg.symbol().size(e.options.lollipopSize).type(e.getLollipopShapeFn()));var i=n.datum().location;delete e.highlighted[i]},MutationDiagram.prototype.fadeIn=function(t,e){var n=this;t.transition().style("opacity",1).duration(n.options.fadeDuration).each("end",function(){_.isFunction(e)&&e(this)})},MutationDiagram.prototype.fadeOut=function(t,e){var n=this;t.transition().style("opacity",0).duration(n.options.fadeDuration).each("end",function(){_.isFunction(e)&&e(this)})},MutationDiagram.prototype.getSelectedElements=function(){var t=this,e=[];for(var n in t.highlighted)e.push(t.highlighted[n]);return e},MutationDiagram.prototype.isFiltered=function(){var t=this,e=!1;return PileupUtil.countMutations(t.pileups)';var f=function(t){if(cbio.util.getWindowOrigin()==t.origin)if("ready"==t.data.type)l&&(s=cbio.util.getTargetDocument("jsmol_frame"));else if("menu"==t.data.type)u&&("visible"==t.data.content?u.css("overflow","visible"):"hidden"==t.data.content&&u.css("overflow","hidden"));else if("done"==t.data.type){var e=p[t.data.scriptId];if(null!=e){delete p[t.data.scriptId];var n=e.callback;n&&_.isFunction(n)&&n()}_.isEmpty(d)||(e=d.shift(),p[e.data.scriptId]=e,l.postMessage(e.data,c))}};window.addEventListener("message",f,!1)}function e(t){t&&r&&(t.empty(),t.append(r),u=t),l=cbio.util.getTargetWindow("jsmol_frame"),l||console.log("warning: JSmol frame cannot be initialized properly")}function n(t,e){if(l){m=(m+1)%1e6;var n={type:"script",content:t,scriptId:"script_"+m};i(n,e)}}function i(t,e){var n={data:t,callback:e};_.isEmpty(d)?(p[n.data.scriptId]=n,l.postMessage(t,c)):d.push(n)}var a=null,o=null,r=null,l=null,s=null,u=null,c=cbio.util.getWindowOrigin(),d=[],p={},m=0,h={use:"HTML5",j2sPath:"js/lib/jsmol/j2s",disableJ2SLoadMonitor:!0,disableInitialConsole:!0};return{init:t,updateContainer:e,script:n}}function JmolScriptGenerator(){function t(t){return"load="+t+";"}function e(){return"select all;"}function n(){return"select none;"}function i(t){return D[t]}function a(t){return"color ["+P(t)+"];"}function o(t){return"select :"+t+";"}function r(t){return"select :"+t+" and helix;"}function l(t){return"select :"+t+" and sheet;"}function s(t){var e="@{{:"+t+"}.atomNo.min}",n="@{{:"+t+"}.atomNo.max}";return'color atoms property atomNo "roygb" range '+e+" "+n+";"}function u(t){return"color atoms CPK;"}function c(){return"restrict protein;"}function d(t){return t>0?"color translucent;":"color opaque;"}function p(t){var e=function(t){var e="";return null!=t&&t.length>0&&(e+="^"+t),e},n=t.start.pdbPos||t.start.pdbPosition,i=t.end.pdbPos||t.end.pdbPosition,a=n+e(t.start.insertion);return i>n&&(a+="-"+i+e(t.end.insertion)),a}function m(t,e){return"select ("+t.join(", ")+") and :"+e+";"}function h(t,e){return"select (("+t.join(", ")+") and :"+e+" and sidechain) or (("+t.join(", ")+") and :"+e+" and *.CA);"}function f(){return"wireframe 0.15; spacefill 25%;"}function g(){return"wireframe OFF; spacefill OFF;"}function v(t,e){var n=this,i=n.scriptPosition(t);return"center "+i+":"+e+";"}function _(){return"center;"}function y(){return"zoom in;"}function b(){return"zoom out;"}function T(t){return"spin "+t+";"}function C(t,e,n,i){var a=this,o=[];o.push(a.selectPositions(t,i.chainId)),o.push(a.setColor(e));var r="none"!=n.displaySideChain;return o=o.concat(a.generateSideChainScript(t,r,n,i))}function P(t){return t.replace("#","x")}var D={ballAndStick:"wireframe ONLY; wireframe 0.15; spacefill 20%;",spaceFilling:"spacefill ONLY; spacefill 100%;",ribbon:"ribbon ONLY;",cartoon:"cartoon ONLY;",trace:"trace ONLY;"};this.loadPdb=t,this.selectAll=e,this.selectNone=n,this.setScheme=i,this.setColor=a,this.selectChain=o,this.selectAlphaHelix=r,this.selectBetaSheet=l,this.rainbowColor=s,this.cpkColor=u,this.hideBoundMolecules=c,this.setTransparency=d,this.scriptPosition=p,this.selectPositions=m,this.selectSideChains=h,this.enableBallAndStick=f,this.disableBallAndStick=g,this.highlightScript=C,this.center=v,this.defaultZoomIn=y,this.defaultZoomOut=b,this.defaultCenter=_,this.spin=T}function JmolWrapper(t){function e(t,e){s=jQuery.extend(!0,{},l,e),delete Jmol._tracker,o=Jmol.getApplet(t,s),r=$("#"+t+"_appletinfotablediv"),r.hide()}function n(t){null!=r&&(t.append(r),r.show())}function i(t,e){Jmol.script(o,t),_.isFunction(e)&&e()}function a(t){return t?{jarPath:"js/lib/jmol/",jarFile:"JmolAppletSigned.jar",disableJ2SLoadMonitor:!0,disableInitialConsole:!0}:{use:"HTML5",j2sPath:"js/lib/jsmol/j2s",disableJ2SLoadMonitor:!0,disableInitialConsole:!0}}var o=null,r=null,l=a(t),s=null;return{init:e,updateContainer:n,script:i}}function MergedAlignmentSegmentor(t){function e(){return o=r;r++)e.push(r);return t.start.insertion&&(e[0]+="^"+t.start.insertion),e.length>1&&t.end.insertion&&(e[e.length-1]+="^"+t.end.insertion),e}function s(t,e){return P={rescode:t,chain:e},""}function u(t,e){return P={rescode:t,chain:e},""}function c(t,e,n,i){var a=this,o=[""];a.selectPositions(t,i.chainId),a.setColor(e);var r="none"!=n.displaySideChain;return a.generateSideChainScript(t,r,n,i),o}function d(){var t=_.extend({},D,S.ballAndStick);return t.sphere.color=w,t.stick.color=w,C.setStyle(P,t),""}function p(){return""}function m(t){return P={chain:t},i("spectrum"),""}function h(t){return P={chain:t},_.each(D,function(t){delete t.color,t.colors=$3Dmol.elementColors.defaultColors}),C.setStyle(P,D),""}function f(t){return t.replace("#","0x")}function g(t){C=t}function v(t){T=t}function y(){var t={resn:["asp","glu","arg","lys","his","asn","thr","cys","gln","tyr","ser","gly","ala","leu","val","ile","met","trp","phe","pro","ASP","GLU","ARG","LYS","HIS","ASN","THR","CYS","GLN","TYR","SER","GLY","ALA","LEU","VAL","ILE","MET","TRP","PHE","PRO"],invert:!0},e={sphere:{hidden:!0}};C.setStyle(t,e)}function b(t){_.each(D,function(e){e.opacity=(10-t)/10}),C.setStyle(P,D)}var T=null,C=null,P=null,D=null,w=null,S={ballAndStick:{stick:{},sphere:{scale:.25}},spaceFilling:{sphere:{scale:.6}},cartoon:{cartoon:{}},ribbon:{cartoon:{style:"ribbon"}},trace:{cartoon:{style:"trace"}}};this.setViewer=g,this.setPdbUri=v,this.loadPdb=t,this.selectAll=e,this.setScheme=n,this.setColor=i,this.selectChain=a,this.selectAlphaHelix=o,this.selectBetaSheet=r,this.scriptPosition=l,this.selectPositions=s,this.selectSideChains=u,this.highlightScript=c,this.rainbowColor=m,this.cpkColor=h,this.enableBallAndStick=d,this.disableBallAndStick=p,this.hideBoundMolecules=y,this.setTransparency=b}function Mol3DWrapper(){function t(t,e){o=jQuery.extend(!0,{},a,e),$(e.el).append("
");var n=$("#"+t);n.hide();var i=$3Dmol.createViewer(n,{defaultcolors:$3Dmol.elementColors.rasmol});i.setBackgroundColor(16777215),r=i}function e(t){null!=r&&r.setContainer(t)}function n(t,e){null!=t&&null!=r&&r.render(),_.isFunction(e)&&e()}function i(){return r}var a={},o=null,r=null;return{init:t,updateContainer:e,getViewer:i,script:n}}function MolScriptGenerator(){this.loadPdb=function(t){return""},this.selectAll=function(){return""},this.selectNone=function(){return""},this.setScheme=function(t){return""},this.setColor=function(t){return""},this.selectChain=function(t){return""},this.selectAlphaHelix=function(t){return""},this.selectBetaSheet=function(t){return""},this.rainbowColor=function(t){return""},this.cpkColor=function(t){return""},this.hideBoundMolecules=function(){return""},this.setTransparency=function(t){return""},this.scriptPosition=function(t){return""},this.selectPositions=function(t,e){return""},this.selectSideChains=function(t,e){return""},this.enableBallAndStick=function(){return""},this.disableBallAndStick=function(){return""},this.center=function(t,e){return""},this.zoom=function(t){return""},this.defaultZoomIn=function(){return""},this.defaultZoomOut=function(){return""},this.defaultCenter=function(){return""},this.spin=function(t){return""},this.highlightScript=function(t,e,n,i){return[]},this.generateVisualStyleScript=function(t,e,n){var i=this,a=[];return a.push(i.selectAll()),a.push(i.setScheme(n.proteinScheme)),a.push(i.setColor(n.defaultColor)),a.push(i.setTransparency(n.defaultTranslucency)),a.push(i.selectChain(e.chainId)),a.push(i.setColor(n.chainColor)),a.push(i.setTransparency(n.chainTranslucency)),a.push(i.selectChain(e.chainId)),"byAtomType"==n.colorProteins?a.push(i.cpkColor(e.chainId)):"bySecondaryStructure"==n.colorProteins?(a.push(i.selectAlphaHelix(e.chainId)),a.push(i.setColor(n.structureColors.alphaHelix)),a.push(i.selectBetaSheet(e.chainId)),a.push(i.setColor(n.structureColors.betaSheet))):"byChain"==n.colorProteins&&(a.push(i.selectChain(e.chainId)),a.push(i.rainbowColor(e.chainId))),_.each(_.keys(t),function(o){a.push(i.selectPositions(t[o],e.chainId)),"byMutationType"==n.colorMutations?a.push(i.setColor(o)):"uniform"==n.colorMutations&&a.push(i.setColor(n.mutationColor)),a=a.concat(i.generateSideChainScript(t[o],"all"==n.displaySideChain,n,e))}),n.restrictProtein&&a.push(i.hideBoundMolecules()),a},this.generateSideChainScript=function(t,e,n,i){var a=this,o=[];return"spaceFilling"!=n.proteinScheme&&(o.push(a.selectSideChains(t,i.chainId)),e?o.push(a.enableBallAndStick()):o.push(a.disableBallAndStick())),o},this.generateHighlightScript=function(t,e,n,i){var a=this,o=[];if(!_.isEmpty(t)){var r=a.highlightScriptPositions(t);o=o.concat(a.highlightScript(r,e,n,i))}return o},this.highlightScriptPositions=function(t){var e=this,n=[];return _.each(t,function(t){n.push(e.scriptPosition(t))}),n}}function MutationInputParser(){function t(t){var n=new MutationCollection,a=t.split("\n");if(a.length>0)for(var o=i(a[0]),r=1;r0&&n.push(e(a[r],o));return l=n,n}function e(t,e){var i=new MutationModel,a=t.split(" "),o={};return _.each(_.keys(d),function(t){var i=n(t,a,e);i&&(o[t]=i)}),o.mutationId=o.mutationId||r(),o.mutationSid=o.mutationSid||o.mutationId,o.variantKey=VariantAnnotationUtil.generateVariantKey(o),i.set(o),i}function n(t,e,n){var i=d[t],a=n[i],o=void 0;return null!=a&&(o=e[a]||void 0),o}function i(t){var e=t.split(" "),n={};return _.each(e,function(t,e){n[t.toLowerCase()]=e}),n}function a(){if(null==l)return[];if(null==u){var t={};l.each(function(e,n){null!=e.get("caseId")&&e.get("caseId").length>0&&(t[e.get("caseId")]=e.get("caseId"))}),u=_.values(t)}return u}function o(){if(null==l)return[];if(null==s){var t={};l.each(function(e,n){null!=e.get("geneSymbol")&&e.get("geneSymbol").length>0&&(t[e.get("geneSymbol").toUpperCase()]=e.get("geneSymbol").toUpperCase())}),s=_.values(t)}return s}function r(){return c++,"stalone_mut_"+c}var l=null,s=null,u=null,c=0,d={proteinPosEnd:"protein_position_end",uniprotId:"uniprot_id",cancerType:"cancer_type",tumorType:"tumor_type",cancerStudyLink:"cancer_study_link",codonChange:"codon_change",proteinPosStart:"protein_position_start",linkToPatientView:"patient_view_link",geneticProfileId:"genetic_profile_id",mutationCount:"mutation_count",mutationType:"mutation_type",referenceAllele:"reference_allele",uniprotAcc:"uniprot_accession",fisValue:"fis_value",functionalImpactScore:"fis",cancerStudy:"cancer_study",normalRefCount:"normal_ref_count",ncbiBuildNo:"ncbi_build",normalFreq:"normal_frequency",cancerStudyShort:"cancer_study_short",msaLink:"msa_link",mutationStatus:"mutation_status",cna:"copy_number",proteinChange:"protein_change",aminoAcidChange:"amino_acid_change",endPos:"end_position",geneSymbol:"hugo_symbol",tumorFreq:"tumor_frequency",startPos:"start_position",keyword:"keyword",cosmic:"cosmic",validationStatus:"validation_status",mutationSid:"mutation_sid",normalAltCount:"normal_alt_count",variantAllele:"variant_allele",mutationId:"mutation_id",caseId:"sample_id",xVarLink:"xvar_link",pdbLink:"pdb_link",tumorAltCount:"tumor_alt_count",tumorRefCount:"tumor_ref_count",sequencingCenter:"center",chr:"chromosome"};return{parseInput:t,getSampleArray:a,getGeneList:o}}function PymolScriptGenerator(){function t(){return"reinitialize;"}function e(t){return"bg_color "+g(t)+";"}function n(t){return"fetch "+t+", async=0;"}function i(t){return v[t]}function a(t){return"color "+g(t)+", sele;"}function o(t){return"select chain "+t+";"}function r(t){return"select (chain "+t+") and (ss h);"}function l(t){return"select (chain "+t+") and (ss s);"}function s(t,e){return"select (resi "+t.join(",")+") and (chain "+e+");"}function u(t,e){return"select ((resi "+t.join(",")+") and (chain "+e+") and (not name c+n+o));"}function c(t){return"set transparency, "+t/10+", sele;\nset cartoon_transparency, "+t/10+", sele;\nset sphere_transparency, "+t/10+", sele;\nset stick_transparency, "+t/10+", sele;"}function d(){return"show spheres, sele; show sticks, sele; alter sele, vdw=0.50;"}function p(){return"hide spheres, sele; hide sticks, sele;"}function m(t){return"spectrum count, rainbow_rev, sele"}function h(t){return"util.cbaw sele;"}function f(){return"hide everything,not resn asp+glu+arg+lys+his+asn+thr+cys+gln+tyr+ser+gly+ala+leu+val+ile+met+trp+phe+pro"}function g(t){return t.replace("#","0x")}var v={ballAndStick:"hide everything; show spheres; show sticks; alter all, vdw=0.50",spaceFilling:"hide everything; show spheres;",ribbon:"hide everything; show ribbon;",cartoon:"hide everything; show cartoon;",trace:"hide everything; show ribbon;"};this.loadPdb=n,this.setScheme=i,this.setColor=a,this.selectChain=o,this.selectAlphaHelix=r,this.selectBetaSheet=l,this.rainbowColor=m,this.cpkColor=h,this.hideBoundMolecules=f,this.setTransparency=c,this.selectPositions=s,this.selectSideChains=u,this.enableBallAndStick=d,this.disableBallAndStick=p,this.reinitialize=t,this.bgColor=e}function RequestQueue(t){function e(t){c.on(l.newRequestEvent,function(){u||n(t)}),c.on(l.completeEvent,function(){n(t)})}function n(t){var e=_.first(s);s=_.rest(s),e?(u=e,_.isFunction(t)&&t(e)):u=!1}function i(){u=!1,c.trigger(l.completeEvent)}function a(t){s.push(t),c.trigger(l.newRequestEvent)}var o=this,r={completeEvent:"requestQueueProcessComplete",newRequestEvent:"requestQueueNewRequest"},l=jQuery.extend(!0,{},r,t),s=[],u=!1,c={};_.extend(c,Backbone.Events),o.add=a,o.complete=i,o.init=e}function AbstractDataProxy(t){var e=this;e._defaultOpts={initMode:"lazy",servletName:"",data:{}},e._queryQueue=new RequestQueue,e._options=jQuery.extend(!0,{},e._defaultOpts,t),e.init=function(){e._queryQueue.init(function(t){$.ajax(t)}),e.isFullInit()?e.fullInit(e._options):e.lazyInit(e._options)},e.lazyInit=function(t){},e.fullInit=function(t){},e.isFullInit=function(){return!("lazy"===e._options.initMode.toLowerCase())},e.requestData=function(t){var n=t.complete,i={complete:function(t,i){e._queryQueue.complete(),_.isFunction(n)&&n(t,i)}},a=jQuery.extend(!0,{},t,i);e._queryQueue.add(a)}}function ClinicalDataProxy(t){function e(t){r=t.data}function n(t,e){function n(){if(!a||0===_.size(r))return void e(null);var t={study_id:a,attribute_ids:["12_245_PARTC_CONSENTED"],patient_ids:r},n=[];for(var l in t)t.hasOwnProperty(l)&&n.push(l+"="+[].concat(t[l]).join(","));var s=n.join("&")||"?",u={type:"POST",url:o.servletName+"/"+o.subService.patients,data:s,dataType:"json",success:function(t){e(t)},error:function(t){e(null)}};i.requestData(u)}var a,r=[],l=null;try{l=window.QuerySession}catch(s){}l?(a=l.cancer_study_ids[0],l.getPatientSampleIdMap().then(function(e){for(var i=0;i0&&a?(o=o.join(","),a.getAnnotationData(o,function(t){VariantAnnotationUtil.addAnnotationData(i,t),_.isFunction(n)&&n(e)})):_.isFunction(n)&&n(e)},pdbMatch:function(t,e,n){var a=e.mutations||e.mutationTable.getMutations(),o=e.gene||e.mutationTable.getGene(),r=t.pdbProxy,l=i[o],s=l.model.uniprotId;a&&r&&s?r.getPdbRowData(s,function(t){PdbDataUtil.addPdbMatchData(a,t),_.isFunction(n)&&n(e)}):_.isFunction(n)&&n(e)},cBioPortal:function(t,e,n){var i=t.pancanProxy,a=e.mutationUtil||e.mutationTable.getMutationUtil(),o=e.mutations||e.mutationTable.getMutations();i.getPancanData({cmd:"byProteinPos"},a,function(t){i.getPancanData({cmd:"byHugos"},a,function(i){var a=PancanMutationDataUtil.getMutationFrequencies({protein_pos_start:t,hugo:i});_.each(o,function(t,e){var n=t.get("proteinPosStart");if(n>0){var i=PancanMutationDataUtil.countByKey(a,n)||0;t.set({cBioPortal:i})}else t.set({cBioPortal:0})}),_.isFunction(n)&&n(e,a)})})}},dataProxies:{}},o=jQuery.extend(!0,{},a,t),r={};this.getData=e,this.addView=n}function MutationDataProxy(t){function e(t){var e=t.data,n=e;_.isArray(e)&&(n=new MutationCollection(e)),d.processMutationData(n)}function n(){return m}function i(){return p}function a(){return c.geneList}function o(){return d}function r(t,e){var n=t.trim().split(/\s+/),i=[],a=[],o=d.getMutationGeneMap();if(_.each(n,function(t,e){t=t.toUpperCase();var n=o[t];void 0==n||0==n.length?i.push(t):a=a.concat(n)}),s.isFullInit())e(a);else{var r=function(t){var n=new MutationCollection(t);d.processMutationData(n),a=a.concat(n.models),e(a)};if(i.length>0){var l=c.params;l.geneList=i.join(" ");var u={type:"POST",url:c.servletName,data:l,success:r,error:function(){console.log("[MutationDataProxy.getMutationData] error retrieving mutation data for genetic profiles: "+l.geneticProfiles),r([])},dataType:"json"};s.requestData(u)}else e(a)}}function l(){return!0}var s=this,u={servletName:"getMutationData.json",geneList:"",params:{}},c=jQuery.extend(!0,{},u,t);AbstractDataProxy.call(this,c),c=s._options;var d=new MutationDetailsUtil,p=c.geneList.trim().split(/\s+/),m=c.geneList.trim().split(/\s+/).sort();s.fullInit=e,s.getMutationData=r,s.getGeneList=n,s.getRawGeneList=a,s.getUnsortedGeneList=i,s.getMutationUtil=o,s.hasData=l}function PancanMutationDataProxy(t){function e(t){var e=t.data;c=e.byKeyword,d=e.byProteinChange,m=e.byGeneSymbol,p=e.byProteinPosition}function n(t,e,n){var a=t.cmd,o=t.q;if(null==a)n(null);else if("byKeywords"==a){var r=null==o?e.getAllKeywords():o.split(",");i(a,r,c,["keyword"],n)}else if("byHugos"==a){var l=null==o?e.getAllGenes():o.split(",");i(a,l,m,["hugo"],n)}else if("byProteinChanges"==a){var s=null==o?e.getAllProteinChanges():o.split(",");i(a,s,d,["protein_change"],n)}else if("byProteinPos"==a){var u=null==o?e.getAllProteinPosStarts():o.split(",");i(a,u,p,["hugo","protein_pos_start"],n)}else n(null)}function i(t,e,n,i,s){var c=o(e,n),d=r(c);if(d.length>0&&!l.isFullInit()){var p={type:"POST",url:u.servletName,data:{cmd:t,q:d.join(",")},success:function(t){a(t,c,n,i,s)},dataType:"json"};l.requestData(p)}else a([],c,n,i,s)}function a(t,e,n,i,a){_.each(t,function(t,a){var o=[];_.each(i,function(e,n){o.push(t[e])});var r=o.join("_");null==n[r]&&(n[r]=[]),null==e[r]&&(e[r]=[]),n[r].push(t),e[r].push(t)});var o=[];_.each(e,function(t){o=o.concat(t)}),a(o)}function o(t,e){var n={};return _.each(t,function(t){n[t]=e[t]}),n}function r(t){var e=[];return _.each(_.keys(t),function(n){null==t[n]&&e.push(n)}),e}var l=this,s={servletName:"pancancerMutations.json"},u=jQuery.extend(!0,{},s,t);AbstractDataProxy.call(this,u),u=l._options;var c={},d={},p={},m={};l.fullInit=e,l.getPancanData=n}function PdbDataProxy(t){function e(t){var e=t.data;_.each(_.keys(e.pdbData),function(t){var n=PdbDataUtil.processPdbData(e.pdbData[t]);m[t]=n,h[t]=PdbDataUtil.allocateChainRows(n)}),f=e.infoData,g=e.summaryData,v=e.positionData}function n(t,e,n){var a=e.alignments,o=i(t,e);if(u.isFullInit()||null!=v[o])return void n(v[o]||{});var r=p.getProteinPositions(t),l={};_.each(r,function(t,n){t.start>-1&&t.start>=e.mergedAlignment.uniprotFrom&&t.start<=e.mergedAlignment.uniprotTo&&(l[t.start]=t.start),t.end>t.start&&t.end>=e.mergedAlignment.uniprotFrom&&t.end<=e.mergedAlignment.uniprotTo&&(l[t.end]=t.end)});var s=_.values(l),c=[];a.each(function(t,e){c.push(t.alignmentId)});var m=function(e){var i={},a=p.getMutationGeneMap()[t],r=e.positionMap||e;if(null!=r&&_.size(r)>0)for(var l=0;l0&&(s=s[0]);var u=s,c=a[l].get("mutationType");null!=c&&"in_frame_del"===c.toLowerCase()&&(u=r[a[l].get("proteinPosEnd")]||u,_.isArray(u)&&_.size(u)>0&&(u=u[0])),null!=s&&null!=u&&(i[a[l].get("mutationId")]={start:s,end:u})}o&&(v[o]=i),n(i)};if(s.length>0){var h=d.servletName;d.subService&&d.subService.map&&(h=h+"/"+d.subService.map);var f={type:"POST",url:h,data:{positions:s.join(d.listJoiner),alignments:c.join(d.listJoiner)},success:m,dataType:"json"};u.requestData(f)}else n({})}function i(t,e){var n=null;return e.alignments.length>0&&(n=t+"_"+e.alignments.at(0).pdbId+"_"+e.chainId),n}function a(t,e){if(u.isFullInit())return void e(m[t]);if(void 0==m[t]){var n=function(n){var i=PdbDataUtil.processPdbData(n);m[t]=i,e(i)},i=d.servletName;d.subService&&d.subService.alignmentByUniprot&&(i=i+"/"+d.subService.alignmentByUniprot);var a={type:"POST",url:i,data:{uniprotId:t,uniprotIds:t},success:n,dataType:"json"};u.requestData(a)}else e(m[t])}function o(t,e){u.isFullInit()||void 0!=h[t]?e(h[t]):a(t,function(n){var i=PdbDataUtil.allocateChainRows(n);h[t]=i,e(i)})}function r(t,e){if(u.isFullInit()||void 0!=g[t])e(g[t]);else{var n=function(n){var i=n;_.isArray(i)&&_.size(i)>0&&(i=i[0]),g[t]=i,e(i)},i=d.servletName;d.subService&&d.subService.summary&&(i=i+"/"+d.subService.summary);var a={type:"POST",url:i,data:{uniprotId:t,uniprotIds:t,type:"summary"},success:n,dataType:"json"};u.requestData(a)}}function l(t,e){var n=function(t){var n=t&&t.alignmentCount>0;e(n)};r(t,n)}function s(t,e){var n=t.trim().split(/\s+/),i=[],a={};if(_.each(n,function(t,e){var n=f[t];void 0==n||0==n.length?i.push(t):a[t]=n}),u.isFullInit())return void e(a);var o={};if(i.length>0){var r=function(t){var i=t;_.isArray(t)&&(i=_.indexBy(t,"pdbId")),_.each(n,function(t,e){null!=i[t]&&(f[t]=i[t],a[t]=i[t])}),e(a)};o.pdbIds=i.join(d.listJoiner);var l=d.servletName;d.subService&&d.subService.header&&(l=l+"/"+d.subService.header);var s={type:"POST",url:l,data:o,success:r,dataType:"json"};u.requestData(s)}else e(a)}var u=this,c={servletName:"pdb_annotation",subService:{alignmentByPdb:"alignment/byPdb",alignmentByUniprot:"alignment/byUniprot",header:"header",map:"map",summary:"summary"},listJoiner:",",mutationUtil:{}},d=jQuery.extend(!0,{},c,t);AbstractDataProxy.call(this,d),d=u._options;var p=d.mutationUtil,m={},h={},f={},g={},v={};u.fullInit=e,u.hasPdbData=l,u.getPdbData=a,u.getPdbRowData=o,u.getPdbInfo=s,u.getPositionMap=n}function PfamDataProxy(t){function e(t){r=t.data}function n(t,e){var n=t.geneSymbol;if(null==n)return void e(null);if(void 0==r[n]){if(i.isFullInit())return void e(null);var a=function(t){r[n]=t,e(t)},l={type:"POST",url:o.servletName,data:t,success:a,dataType:"json"};i.requestData(l)}else e(r[n])}var i=this,a={servletName:"getPfamSequence.json"},o=jQuery.extend(!0,{},a,t);AbstractDataProxy.call(this,o),o=i._options;var r={};i.fullInit=e,i.getPfamData=n}function PortalDataProxy(t){function e(t){r=t.data}function n(t,e){var n={},a={};_.each(_.keys(t),function(e,i){null==r[e]?a[e]=t[e]:n[e]=r[e]});var l=function(t){_.each(_.keys(t),function(e,n){r[e]=t[e]}),_.isFunction(e)&&e(jQuery.extend(!0,{},n,t))};if(_.isEmpty(a))l(n);else{var s={type:"POST",url:o.servletName,data:a,success:l,dataType:"json"};i.requestData(s)}}var i=this,a={servletName:"portalMetadata.json"},o=jQuery.extend(!0,{},a,t);AbstractDataProxy.call(this,o),o=i._options;var r={};i.fullInit=e,i.getPortalData=n}function VariantAnnotationDataProxy(t){function e(t){o=t.data}function n(t,e){var n=t.trim().split(","),r=[],s=[];if(_.each(n,function(t,e){var n=o[t];void 0==n||_.isEmpty(n)?r.push(t):s=s.concat(n)}),a.isFullInit())e(s);else{var u=function(t){_.each(t,function(t,e){i(t),t.id?o[t.id]=t:t.annotationJSON.id&&(o[t.annotationJSON.id]=t)}),s=s.concat(t),e(s)};if(r.length>0){var c=r.join(","),d={type:"POST",url:l.servletName,data:{variants:c},success:u,error:function(){console.log("[VariantDataProxy.getAnnotationData] error retrieving annotation data for variants: "+c),u([])},dataType:"json"};a.requestData(d)}else e(s)}}function i(t){if(_.isString(t.annotationJSON)){var e=JSON.parse(t.annotationJSON);_.isArray(e)&&e.length>0&&(e=e[0]),t.annotationJSON=e}}var a=this,o={},r={servletName:"variant_annotation/hgvs"},l=jQuery.extend(!0,{},r,t);AbstractDataProxy.call(this,l),l=a._options,a.fullInit=e,a.getAnnotationData=n}function AdvancedDataTable(t){var e=this,n=null;e._defaultOpts={el:"",columns:{},columnOrder:[],columnVisibility:{},columnSearch:{},columnRender:{},columnSort:{},columnFilter:{},columnData:{},columnTooltips:{},eventListeners:{},customSort:{},filteringDelay:0,dataTableOpts:{}},e._options=jQuery.extend(!0,{},e._defaultOpts,t),e._dispatcher={},_.extend(e._dispatcher,Backbone.Events),e._dataTable=null,e._visibilityValue=function(t){return"hidden"},e._searchValue=function(t){return!1},e.renderTable=function(t){var i=e._options.columnOrder,a=n=DataTableUtil.buildColumnIndexMap(i),o=DataTableUtil.buildColumnNameMap(e._options.columns),r=DataTableUtil.buildColumnVisMap(i,e._visibilityValue);e._visiblityMap=r;var l=DataTableUtil.buildColumnSearchMap(i,e._searchValue),s=DataTableUtil.getHiddenColumns(i,a,r),u=DataTableUtil.getExcludedColumns(i,a,r),c=DataTableUtil.getNonSearchableColumns(i,a,l);e._addSortFunctions(),e._dataTable=e._initDataTable($(e._options.el),t,e._options.columns,o,a,s,u,c),e._addEventListeners(a),e._options.filteringDelay>0&&e._dataTable.fnSetFilteringDelay(e._options.filteringDelay)},e._initDataTableOpts=function(t,e,n,i,a,o,r,l){return null},e._initDataTable=function(t,n,i,a,o,r,l,s){var u=e._initDataTableOpts(t,n,i,a,o,r,l,s),c=DataTableUtil.getColumnData(o,e._options.columnRender,e._options.columnSort,e._options.columnFilter,e._options.columnData);return u.aoColumnDefs=u.aoColumnDefs.concat(c),u=jQuery.extend(!0,{},e._options.dataTableOpts,u),t.dataTable(u)},e._addSortFunctions=function(){_.each(_.pairs(e._options.customSort),function(t){var e=t[0],n=t[1];jQuery.fn.dataTableExt.oSort[e]=n})},e._addEventListeners=function(t){null!=e.getDataTable()&&_.each(e._options.eventListeners,function(n){n(e.getDataTable(),e._dispatcher,t)})},e._addColumnTooltips=function(t){t=t||{};var n=$(e._options.el);_.each(_.keys(e._options.columnTooltips),function(i){if("excluded"!=e._visiblityMap[i]){var a=e._options.columnTooltips[i];_.isFunction(a)&&a(n,t)}})},e.getColumnOptions=function(){return e._options.columns},e.getDataTable=function(){return e._dataTable},e.setDataTable=function(t){e._dataTable=t},e.getIndexMap=function(){return n}}function Mutation3dVis(t,e){function n(){V=new Mol3DWrapper,V.init(t,j.appOptions),G.setViewer(V.getViewer()),G.setPdbUri(j.pdbUri)}function i(t){k=$(t);var e=k.find(".mutation-3d-vis-container");e.css("width",j.appOptions.width),e.css("height",j.appOptions.height+j.containerPadding),V.updateContainer(e)}function a(){q="ON"==q?"OFF":"ON";var t=G.spin(q);V.script(t)}function o(){var t=G.generateVisualStyleScript(B,R,j);t=t.concat(w(O)),t=t.join(" "),V.script(t)}function r(){if(null!=k){k.show();var t=parseInt(k.css("top"));0>t&&(null!=z&&z>0?k.css("top",z):k.css("top",0))}}function l(){if(null!=k){var t=parseInt(k.css("top"));t>0&&(z=t),k.css("top",-9999)}}function s(){null!=k&&(k.css({overflow:"hidden",height:j.minimizedHeight}),N=!0)}function u(){null!=k&&(k.css({overflow:"",height:""}),N=!1)}function c(){null!=k&&(N?u():s())}function d(){var t=parseInt(k.css("top")),e=-9999==t||k.is(":hidden");return!e}function p(t,e,n){var i=[];if(O={},!t||!e)return i;R=e,U=t,i=h(t,e);var a=[],o=function(){a.push(r),a=a.concat(G.generateVisualStyleScript(B,R,j)),a=a.join(" "),V.script(a,n),y()},r=G.loadPdb(t,o);return"$3Dmol"!=r&&o(),i}function m(){var t=[];if(O={},null==U||null==R)return t;t=h(U,R);var e=[];return e=e.concat(G.generateVisualStyleScript(B,R,j)),e=e.join(" "),V.script(e),t}function h(t,e){var n=f(t,e,j,G);return B=n.colorMap,n.mappedMutations}function f(t,e,n,i){var a=[],o={},r=n.mutationColor;return _.each(_.keys(e.positionMap),function(l){var s=e.positionMap[l];if(_.isFunction(n.mutationColorMapper)&&(r=n.mutationColorMapper(l,t,e)),null!=r){null==o[r]&&(o[r]={});var u=i.scriptPosition(s);o[r][u]=u,a.push(l)}}),_.each(o,function(t,e,n){n[e]=_.values(t)}),{colorMap:o,mappedMutations:a}}function g(){if(1!=_.size(O))return!1;var t=[];return _.each(O,function(e){t=t.concat(S(e))}),t=t.join(" "),V.script(t),!0}function v(){var t=[];t.push(G.defaultCenter()),t=t.join(" "),V.script(t)}function y(){V.getViewer&&V.getViewer().resize()}function b(t){if(null==R)return!1;var e=t.mutations[0].get("mutationId"),n=M(e);return n.length>0?(n=n.join(" "),V.script(n),!0):(T(),!1)}function T(){var t=[];t.push(G.zoom(j.defaultZoom)),t.push(G.defaultCenter()),t=t.join(" "),V.script(t)}function C(t,e){if(null==R)return 0;e&&(O={});var n=G.generateVisualStyleScript(B,R,j),i=0;return _.each(t,function(t,e){var n=t.mutations[0].get("mutationId"),a=R.positionMap[n];null!=a&&(O[n]=a,i++)}),n=n.concat(w(O)),n=n.join(" "),V.script(n),i}function P(){var t=w(O);t=t.join(" "),V.script(t)}function D(){O={};var t=G.generateVisualStyleScript(B,R,j);t=t.join(" "),V.script(t)}function w(t){return G.generateHighlightScript(t,j.highlightColor,j,R)}function S(t){var e=[];return e.push(G.center(t,R.chainId)),e}function M(t){var e=[],n=R.positionMap[t];return null!=n&&(e.push(G.zoom(j.focusZoom)),e.push(G.center(n,R.chainId))),e}function x(){V.script(G.defaultZoomIn())}function A(){V.script(G.defaultZoomOut())}function I(){V.script(G.zoom(j.defaultZoom))}function E(t){V.script(G.zoom(t))}function L(t){j=jQuery.extend(!0,{},j,t)}function F(){var t=new PymolScriptGenerator,e=[];return e.push(t.reinitialize()),e.push(t.bgColor(j.appOptions.color)),e.push(t.loadPdb(U)),e=e.concat(t.generateVisualStyleScript(B,R,j)),e=e.concat(t.generateHighlightScript(O,j.highlightColor,j,R)),e.push(t.selectNone()),e=e.join("\n")}var k=null,V=null,N=!1,B=null,O={},R=null,U=null,q="OFF",z=null,H={appOptions:{width:400,height:300,debug:!1,color:"white"},pdbUri:"http://www.rcsb.org/pdb/files/",frame:"jsmol_frame.html",proteinScheme:"cartoon",restrictProtein:!1,defaultColor:"#DDDDDD",structureColors:{alphaHelix:"#FFA500",betaSheet:"#0000FF",loop:"#DDDDDD"},defaultTranslucency:5,chainColor:"#888888",chainTranslucency:0,colorProteins:"uniform",colorMutations:"byMutationType",mutationColor:"#8A2BE2",highlightColor:"#FFDD00",highlightGradient:["#FFDD00","#000000"],addGlowEffect:!1,displaySideChain:"highlighted",defaultZoom:100,focusZoom:250,containerPadding:10, +minimizedHeight:10,mutationColorMapper:function(t,e,n){return"#FF0000"}},j=jQuery.extend(!0,{},H,e),G=new Mol3DScriptGenerator;return{init:n,show:r,hide:l,minimize:s,maximize:u,toggleSize:c,isVisible:d,reload:p,refresh:m,resizeViewer:y,focusOn:b,center:g,resetCenter:v,highlight:C,resetHighlight:D,refreshHighlight:P,zoomIn:x,zoomOut:A,zoomActual:I,zoomTo:E,resetFocus:T,updateContainer:i,toggleSpin:a,reapplyStyle:o,updateOptions:L,generatePymolScript:F}}function MutationDetailsTable(t,e,n,i,a){function o(t,a,o,l,s,u,c,d){var p=DataTableUtil.getColumnOptions(o,s),m={aaData:a,aoColumns:p,aoColumnDefs:[{bVisible:!1,aTargets:u},{bSearchable:!1,aTargets:d}],oColVis:{aiExclude:c},oTableTools:{aButtons:[{sExtends:"text",sButtonText:"Download",mColumns:r(o,c),fnCellRender:function(t,e,n,i){var a=t;return-1!=t.indexOf("<")&&-1!=t.indexOf(">")&&(a=$(t).text()),e===s.proteinChange&&(a=a.replace(/(\s)3D/,"")),a.trim()},fnClick:function(t,n){var i=this.fnGetTableData(n),a={filename:"mutation_table_"+e+".tsv",contentType:"text/plain;charset=utf-8",preProcess:!1};cbio.download.initDownload(i,a)}}]},fnDrawCallback:function(a){b._addColumnTooltips({gene:e,mutationUtil:n,dataProxies:i,table:b}),b._addEventListeners(s);var o=a.oPreviousSearch.sSearch;D&&w!=o&&(P.trigger(MutationDetailsEvents.MUTATION_TABLE_FILTERED,t),S=o),w=o,P.trigger(MutationDetailsEvents.MUTATION_TABLE_REDRAWN,t),$(t).find('a[href=""]').remove(),$(t).find('span.mutation-table-additional-protein-change[alt=""]').remove()},fnRowCallback:function(t,e,n,i){var a=e[s.datum].mutation;$(t).attr("id",a.get("mutationId")),$(t).addClass(a.get("mutationSid")),$(t).addClass("mutation-table-data-row")},fnInitComplete:function(e,n){b.setDataTable(this),$(e.nTableWrapper).find(".ColVis_MasterButton").one("click",function(){jQuery.each($(".ColVis_radio"),function(t,e){var n=$(e).siblings(":first").text();$(e).children(":first").attr("title",n)})}),P.trigger(MutationDetailsEvents.MUTATION_TABLE_INITIALIZED,t)},fnHeaderCallback:function(e,n,i,a,o){$(e).find("th").addClass("mutation-details-table-header"),b._addHeaderTooltips(e,l),P.trigger(MutationDetailsEvents.MUTATION_TABLE_HEADER_CREATED,t)}};return m}function r(t,e){for(var n=[],i=0;i<=_.keys(t).length;i++)n.push(i);return _.difference(n,e)}function l(t){var i=C.columnVisibility[t],a=i;return i?_.isFunction(i)&&(a=i(n,e)):a="hidden",a}function s(t){var e=C.columnSearch[t],n=e;return null==e?n=!1:_.isFunction(e)&&(n=e()),n}function u(t){null!=b.getDataTable()&&_.each(C.eventListeners,function(t){t(b.getDataTable(),P,n,e)})}function c(t){D=t}function d(){w="",S=""}function p(){return S}function m(t,e){var n=MutationViewsUtil.defaultTableTooltipOpts(),i={};jQuery.extend(!0,i,n),i.position={my:"bottom center",at:"top center",viewport:$(window)},$(t).find("th").each(function(){var t=$(this).text(),n=e[t];if(null!=n){var a=C.columns[n].tip,o={};_.isString(a)&&(a={content:a}),jQuery.extend(!0,o,i,a),cbio.util.addTargetedQTip(this,o)}})}function h(t,e,n){function i(){P.off(MutationDetailsEvents.MUTATION_TABLE_INITIALIZED,i),a.getData(t,{mutationTable:b},n)}e=e||t,"excluded"===b._visiblityMap[e]||x[t+":"+e]||(x[t+":"+e]=!0,n=n||function(n,i){var a=n.mutationTable;i&&(b.getCustomData()[t]=i),MutationViewsUtil.refreshTableColumn(a.getDataTable(),a.getIndexMap(),e)},null==b.getDataTable()?P.on(MutationDetailsEvents.MUTATION_TABLE_INITIALIZED,i):i())}function f(){var t=null;return n&&(t=n.getMutations()),t}function g(){return M}function v(){return n}function y(){return e}var b=this,T={el:"#mutation_details_table_d3",columns:{datum:{sTitle:"datum",tip:""},mutationId:{sTitle:"Mutation ID",tip:"Mutation ID",sType:"string"},mutationSid:{sTitle:"Mutation SID",tip:"",sType:"string"},caseId:{sTitle:"Sample ID",tip:"Sample ID",sType:"string"},cancerStudy:{sTitle:"Cancer Study",tip:"Cancer Study",sType:"string"},tumorType:{sTitle:"Cancer Type",tip:"Cancer Type",sType:"string"},proteinChange:{sTitle:"AA change",tip:"Protein Change",sType:"numeric"},mutationType:{sTitle:"Type",tip:"Mutation Type",sType:"string",sClass:"center-align-td"},cna:{sTitle:"Copy #",tip:"Copy-number status of the mutated gene",sType:"numeric",sClass:"center-align-td"},cosmic:{sTitle:"COSMIC",tip:"Overlapping mutations in COSMIC",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},mutationStatus:{sTitle:"MS",tip:"Mutation Status",sType:"string",sClass:"center-align-td"},validationStatus:{sTitle:"VS",tip:"Validation Status",sType:"string",sClass:"center-align-td"},mutationAssessor:{sTitle:"Mutation Assessor",tip:"Predicted Functional Impact Score (via Mutation Assessor) for missense mutations",sType:"numeric",sClass:"center-align-td",asSorting:["desc","asc"],sWidth:"2%"},sequencingCenter:{sTitle:"Center",tip:"Sequencing Center",sType:"string",sClass:"center-align-td"},chr:{sTitle:"Chr",tip:"Chromosome",sType:"string"},startPos:{sTitle:"Start Pos",tip:"Start Position",sType:"numeric",sClass:"right-align-td"},endPos:{sTitle:"End Pos",tip:"End Position",sType:"numeric",sClass:"right-align-td"},referenceAllele:{sTitle:"Ref",tip:"Reference Allele",sType:"string"},variantAllele:{sTitle:"Var",tip:"Variant Allele",sType:"string"},tumorFreq:{sTitle:"Allele Freq (T)",tip:"Variant allele frequency
in the tumor sample",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},normalFreq:{sTitle:"Allele Freq (N)",tip:"Variant allele frequency
in the normal sample",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},tumorRefCount:{sTitle:"Var Ref",tip:"Variant Ref Count",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},tumorAltCount:{sTitle:"Var Alt",tip:"Variant Alt Count",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},normalRefCount:{sTitle:"Norm Ref",tip:"Normal Ref Count",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},normalAltCount:{sTitle:"Norm Alt",tip:"Normal Alt Count",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]},igvLink:{sTitle:"BAM",tip:"Link to BAM file",sType:"string",sClass:"center-align-td"},mutationCount:{sTitle:"#Mut in Sample",tip:"Total number of
nonsynonymous mutations
in the sample",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"],sWidth:"2%"},cBioPortal:{sTitle:"cBioPortal",tip:"Mutation frequency in cBioPortal",sType:"numeric",sClass:"right-align-td",asSorting:["desc","asc"]}},columnOrder:["datum","mutationId","mutationSid","caseId","cancerStudy","tumorType","proteinChange","mutationType","cna","cBioPortal","cosmic","mutationStatus","validationStatus","mutationAssessor","sequencingCenter","chr","startPos","endPos","referenceAllele","variantAllele","tumorFreq","normalFreq","tumorRefCount","tumorAltCount","normalRefCount","normalAltCount","igvLink","mutationCount"],columnVisibility:{datum:"excluded",proteinChange:"visible",caseId:function(t,e){return t.containsCaseId(e)?"visible":"hidden"},mutationType:function(t,e){return t.containsMutationType(e)?"visible":"hidden"},mutationAssessor:function(t,e){return t.containsFis(e)?"visible":"hidden"},cosmic:"visible",mutationCount:function(t,e){return t.containsMutationCount(e)?"visible":"hidden"},mutationId:"excluded",mutationSid:"excluded",cancerStudy:"excluded",cna:function(t,e){return t.containsCnaData(e)?"visible":"hidden"},tumorFreq:function(t,e){return t.containsAlleleFreqT(e)?"visible":"hidden"},igvLink:function(t,e){return t.containsIgvLink(e)?"visible":"hidden"},mutationStatus:function(t,e){return t.containsGermline(e)?"visible":"hidden"},validationStatus:function(t,e){return t.containsValidStatus(e)?"visible":"hidden"},tumorType:function(t,e){var n=t.distinctTumorTypeCount(e);return n>1?"visible":"hidden"},cBioPortal:"excluded"},columnSearch:{caseId:!0,mutationId:!0,mutationSid:!0,cancerStudy:!0,proteinChange:!0,tumorType:!0,mutationType:!0},columnRender:{mutationId:function(t){var e=t.mutation,n=e.get("mutationId");return void 0===n?"":n},mutationSid:function(t){var e=t.mutation,n=e.get("mutationSid");return void 0===n?"":n},caseId:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getCaseId(e.get("caseId")),i={};i.linkToPatientView=e.get("linkToPatientView"),i.caseId=n.text,i.caseIdClass=n.style,i.caseIdTip=n.tip;var a=BackboneTemplateCache.getTemplateFn("mutation_table_case_id_template");return a(i)},proteinChange:function(t){var e=t.mutation;if(_.isUndefined(e.get("proteinChange")))return b.requestColumnData("variantAnnotation","proteinChange"),MutationViewsUtil.renderTablePlaceHolder();var n=MutationDetailsTableFormatter.getProteinChange(e),i={};i.proteinChange=n.text,i.proteinChangeClass=n.style,i.proteinChangeTip=n.tip,i.additionalProteinChangeTip=n.additionalTip,_.isUndefined(e.get("pdbMatch"))&&b.requestColumnData("pdbMatch","proteinChange"),i.pdbMatchLink=MutationDetailsTableFormatter.getPdbMatchLink(e);var a=BackboneTemplateCache.getTemplateFn("mutation_table_protein_change_template");return a(i)},cancerStudy:function(t){var e=t.mutation,n={};n.cancerStudy=e.get("cancerStudy"),n.cancerStudyShort=e.get("cancerStudyShort"),n.cancerStudyLink=e.get("cancerStudyLink");var i=BackboneTemplateCache.getTemplateFn("mutation_table_cancer_study_template");return i(n)},tumorType:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getTumorType(e),i={};i.tumorType=n.text,i.tumorTypeClass=n.style,i.tumorTypeTip=n.tip;var a=BackboneTemplateCache.getTemplateFn("mutation_table_tumor_type_template");return a(i)},mutationType:function(t){var e=t.mutation;if(_.isUndefined(e.get("mutationType")))return b.requestColumnData("variantAnnotation","mutationType"),MutationViewsUtil.renderTablePlaceHolder();var n=MutationDetailsTableFormatter.getMutationType(e.get("mutationType")),i={};if(i.mutationTypeClass=n.style,i.mutationTypeText=n.text,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_mutation_type_template");return a(i)},cosmic:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getCosmic(e.getCosmicCount()),i={};if(i.cosmicClass=n.style,i.cosmicCount=n.count,_.isEmpty(n.count))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_cosmic_template");return a(i)},cna:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getCNA(e.get("cna")),i={};if(i.cna=n.text,i.cnaClass=n.style,i.cnaTip=n.tip,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_cna_template");return a(i)},mutationCount:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getIntValue(e.get("mutationCount")),i={};if(i.mutationCount=n.text,i.mutationCountClass=n.style,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_mutation_count_template");return a(i)},normalFreq:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.get("normalAltCount")),i=MutationDetailsTableFormatter.getAlleleFreq(e.get("normalFreq"),e.get("normalAltCount"),e.get("normalRefCount"),"simple-tip"),a={};if(a.normalFreq=i.text,a.normalFreqClass=i.style,a.normalFreqTipClass=i.tipClass,a.normalTotalCount=i.total,a.normalAltCount=n.text,_.isEmpty(i.text))return"";var o=BackboneTemplateCache.getTemplateFn("mutation_table_normal_freq_template");return o(a)},tumorFreq:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.get("tumorAltCount")),i=MutationDetailsTableFormatter.getAlleleFreq(e.get("tumorFreq"),e.get("tumorAltCount"),e.get("tumorRefCount"),"simple-tip"),a={};if(a.tumorFreq=i.text,a.tumorFreqClass=i.style,a.tumorFreqTipClass=i.tipClass,a.tumorTotalCount=i.total,a.tumorAltCount=n.text,_.isEmpty(i.text))return"";var o=BackboneTemplateCache.getTemplateFn("mutation_table_tumor_freq_template");return o(a)},mutationAssessor:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getFis(e.get("functionalImpactScore"),e.get("fisValue")),i={};if(i.fisClass=n.fisClass,i.omaClass=n.omaClass,i.fisText=n.text,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_mutation_assessor_template");return a(i)},mutationStatus:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getMutationStatus(e.get("mutationStatus")),i={};if(i.mutationStatusTip=n.tip,i.mutationStatusClass=n.style,i.mutationStatusText=n.text,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_mutation_status_template");return a(i)},validationStatus:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getValidationStatus(e.get("validationStatus")),i={};if(i.validationStatusTip=n.tip,i.validationStatusClass=n.style,i.validationStatusText=n.text,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_validation_status_template");return a(i)},normalRefCount:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.get("normalRefCount")),i={};if(i.normalRefCount=n.text,i.normalRefCountClass=n.style,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_normal_ref_count_template");return a(i)},normalAltCount:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.get("normalAltCount")),i={};if(i.normalAltCount=n.text,i.normalAltCountClass=n.style,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_normal_alt_count_template");return a(i)},tumorRefCount:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.get("tumorRefCount")),i={};if(i.tumorRefCount=n.text,i.tumorRefCountClass=n.style,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_tumor_ref_count_template");return a(i)},tumorAltCount:function(t){var e=t.mutation,n=MutationDetailsTableFormatter.getAlleleCount(e.get("tumorAltCount")),i={};if(i.tumorAltCount=n.text,i.tumorAltCountClass=n.style,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_tumor_alt_count_template");return a(i)},startPos:function(t){var e=t.mutation;if(_.isUndefined(e.get("startPos")))return b.requestColumnData("variantAnnotation","startPos"),MutationViewsUtil.renderTablePlaceHolder();var n=MutationDetailsTableFormatter.getIntValue(e.get("startPos")),i={};if(i.startPos=n.text,i.startPosClass=n.style,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_start_pos_template");return a(i)},endPos:function(t){var e=t.mutation;if(_.isUndefined(e.get("endPos")))return b.requestColumnData("variantAnnotation","endPos"),MutationViewsUtil.renderTablePlaceHolder();var n=MutationDetailsTableFormatter.getIntValue(e.get("endPos")),i={};if(i.endPos=n.text,i.endPosClass=n.style,_.isEmpty(n.text))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_end_pos_template");return a(i)},sequencingCenter:function(t){var e=t.mutation,n=e.get("sequencingCenter");return void 0===n?"":n},chr:function(t){var e=t.mutation;return _.isUndefined(e.get("chr"))?(b.requestColumnData("variantAnnotation","chr"),MutationViewsUtil.renderTablePlaceHolder()):e.get("chr")||""},referenceAllele:function(t){var e=t.mutation;return _.isUndefined(e.get("referenceAllele"))?(b.requestColumnData("variantAnnotation","referenceAllele"),MutationViewsUtil.renderTablePlaceHolder()):e.get("referenceAllele")||""},variantAllele:function(t){var e=t.mutation;return _.isUndefined(e.get("variantAllele"))?(b.requestColumnData("variantAnnotation","variantAllele"),MutationViewsUtil.renderTablePlaceHolder()):e.get("variantAllele")||""},igvLink:function(t){var e=t.mutation,n={};n.igvLink=MutationDetailsTableFormatter.getIgvLink(e);var i=BackboneTemplateCache.getTemplateFn("mutation_table_igv_link_template");return i(n)},cBioPortal:function(t){var e=t.mutation;if(_.isUndefined(e.get("cBioPortal")))return b.requestColumnData("cBioPortal"),MutationViewsUtil.renderTablePlaceHolder();var n=MutationDetailsTableFormatter.getCbioPortal(e.get("cBioPortal")),i={};if(i.portalFrequency=n.frequency,i.portalClass=n.style,_.isEmpty(n.frequency))return"";var a=BackboneTemplateCache.getTemplateFn("mutation_table_cbio_portal_template");return a(i)}},columnTooltips:{simple:function(t,e){var n=MutationViewsUtil.defaultTableTooltipOpts();cbio.util.addTargetedQTip($(t).find(".simple-tip"),n)},cosmic:function(t,e){var n=e.gene,i=e.mutationUtil,a=MutationViewsUtil.defaultTableTooltipOpts();$(t).find(".mutation_table_cosmic").each(function(){var t=this,e=$(t).closest("tr.mutation-table-data-row").attr("id"),o=i.getMutationIdMap()[e],r={};jQuery.extend(!0,r,a),r.content={text:"NA"},r.events={render:function(e,i){var a={cosmic:o.get("cosmic"),keyword:o.get("keyword"),geneSymbol:n,total:$(t).text()},r=$(this).find(".qtip-content"),l=new CosmicTipView({el:r,model:a});l.render()}},cbio.util.addTargetedQTip(t,r)})},mutationAssessor:function(t,e){var n=(e.gene,e.mutationUtil),i=MutationViewsUtil.defaultTableTooltipOpts();$(t).find(".oma_link").each(function(){var t=$(this).closest("tr.mutation-table-data-row").attr("id"),e=n.getMutationIdMap()[t],a=MutationDetailsTableFormatter.getFis(e.get("functionalImpactScore"),e.get("fisValue")),o={};jQuery.extend(!0,o,i),o.content={text:"NA"},o.events={render:function(t,n){var i={impact:a.value,xvia:e.get("xVarLink").replace("getma.org","mutationassessor.org/r2"),msaLink:e.get("msaLink").replace("getma.org","mutationassessor.org/r2"),pdbLink:e.get("pdbLink").replace("getma.org","mutationassessor.org/r2")},o=$(this).find(".qtip-content"),r=new PredictedImpactTipView({el:o,model:i});r.render()}},cbio.util.addTargetedQTip(this,o)})},cBioPortal:function(t,e){var n=e.gene,i=e.mutationUtil,a=e.dataProxies.portalProxy,o=e.table,r=function(e,a,o){$(t).find(".mutation_table_cbio_portal").each(function(t,r){var l=$(this).closest("tr.mutation-table-data-row").attr("id"),s=i.getMutationIdMap()[l],u=o||s.get("cancerStudy");cbio.util.addTargetedQTip(r,{content:{text:"pancancer mutation bar chart is broken"},events:{render:function(t,i){var o={pancanMutationFreq:e,cancerStudyMetaData:a,cancerStudyName:u,geneSymbol:n,keyword:s.get("keyword"),proteinPosStart:s.get("proteinPosStart"),mutationType:s.get("mutationType"),qtipApi:i},r=$(this),l=new PancanMutationHistTipView({el:r,model:o});l.render()}},hide:{fixed:!0,delay:100},style:{classes:"qtip-light qtip-rounded qtip-shadow",tip:!0},position:{my:"center right",at:"center left",viewport:$(window)}})})};null!=o.getCustomData().cBioPortal&&a.getPortalData({cancerStudyMetaData:!0,cancerStudyName:!0},function(t){r(o.getCustomData().cBioPortal,t.cancerStudyMetaData,t.cancerStudyName)})}},eventListeners:{windowResize:function(t,e,n,i){$(window).one("resize",function(){t.is(":visible")&&t.fnAdjustColumnSizing()})},igvLink:function(t,e,n,i){$(t).find(".igv-link").off("click").on("click",function(t){t.preventDefault();var e=$(this).closest("tr.mutation-table-data-row").attr("id"),i=n.getMutationIdMap()[e],a=i.get("igvLink");$.getJSON(a,function(t){prepIGVLaunch(t.bamFileUrl,t.encodedLocus,t.referenceGenome,t.trackName)})})},proteinChange3d:function(t,e,n,i){$(t).find(".mutation-table-3d-link").off("click").on("click",function(t){t.preventDefault();var n=$(this).closest("tr.mutation-table-data-row").attr("id");e.trigger(MutationDetailsEvents.PDB_LINK_CLICKED,n)})},proteinChange:function(t,e,n,i){$(t).find(".mutation-table-protein-change a").off("click").on("click",function(t){t.preventDefault();var n=$(this).closest("tr.mutation-table-data-row").attr("id");e.trigger(MutationDetailsEvents.PROTEIN_CHANGE_LINK_CLICKED,n)})}},columnSort:{mutationId:function(t){var e=t.mutation;return void 0===e.get("mutationId")?"":e.get("mutationId")},mutationSid:function(t){var e=t.mutation;return void 0===e.get("mutationSid")?"":e.get("mutationSid")},caseId:function(t){var e=t.mutation;return void 0===e.get("caseId")?"":e.get("caseId")},proteinChange:function(t){var e=t.mutation.get("proteinChange"),n=/[A-Za-z][0-9]+./g,i=/[0-9]+/g,a=/[^0-9]+/g,o=function(t){var e=t[0].match(a);if(e&&e.length>0){var n=e.join("");e=[];for(var i=0;i0){var s=r[0];return l&&l.length>0&&(s+="."+l.join("")),parseFloat(s)}return-(1/0)},cancerStudy:function(t){var e=t.mutation,n=e.get("cancerStudy");return void 0===n?"":n},tumorType:function(t){var e=t.mutation,n=e.get("tumorType");return void 0===n?"":n},mutationType:function(t){var e=t.mutation,n=e.get("mutationType");return void 0===n?"":n},cosmic:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.getCosmicCount())},cna:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.get("cna"))},mutationCount:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.get("mutationCount"))},normalFreq:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignFloatValue(e.get("normalFreq"))},tumorFreq:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignFloatValue(e.get("tumorFreq"))},mutationAssessor:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignValueToPredictedImpact(e.get("functionalImpactScore"),e.get("fisValue"))},mutationStatus:function(t){var e=t.mutation,n=e.get("mutationStatus");return void 0===n?"":n},validationStatus:function(t){var e=t.mutation,n=e.get("validationStatus");return void 0===n?"":n},normalRefCount:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.get("normalRefCount"))},normalAltCount:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.get("normalAltCount"))},tumorRefCount:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.get("tumorRefCount"))},tumorAltCount:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.get("tumorAltCount"))},startPos:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.get("startPos"))},endPos:function(t){var e=t.mutation;return MutationDetailsTableFormatter.assignIntValue(e.get("endPos"))},sequencingCenter:function(t){var e=t.mutation,n=e.get("sequencingCenter");return void 0===n&&(n=""),n},chr:function(t){var e=t.mutation,n=e.get("chr");return void 0===n?"":n},referenceAllele:function(t){var e=t.mutation,n=e.get("referenceAllele");return void 0===n?"":n},variantAllele:function(t){var e=t.mutation,n=e.get("variantAllele");return void 0===n?"":n},igvLink:function(t){var e=t.mutation,n=e.get("igvLink");return void 0===n?"":n},cBioPortal:function(t){var e=t.cBioPortal;return e||0}},columnFilter:{proteinChange:function(t){return t.mutation.get("proteinChange")||""},mutationType:function(t){var e=MutationDetailsTableFormatter.getMutationType(t.mutation.get("mutationType"));return e.text},cosmic:function(t){return t.mutation.getCosmicCount()||""},cna:function(t){return t.mutation.get("cna")||""},mutationCount:function(t){return t.mutation.get("mutationCount")||""},normalFreq:function(t){return t.mutation.get("normalFreq")||""},tumorFreq:function(t){return t.mutation.get("tumorFreq")||""},mutationAssessor:function(t){return t.mutation.get("functionalImpactScore")||""},normalRefCount:function(t){return t.mutation.get("normalRefCount")||""},normalAltCount:function(t){return t.mutation.get("normalAltCount")||""},tumorRefCount:function(t){return t.mutation.get("tumorRefCount")||""},tumorAltCount:function(t){return t.mutation.get("tumorAltCount")||""},startPos:function(t){return t.mutation.get("startPos")||""},endPos:function(t){return t.mutation.get("endPos")||""}},columnData:{},filteringDelay:600,dataTableOpts:{sDom:'<"H"<"mutation_datatables_filter"f>C<"mutation_datatables_info"i>>t<"F"<"mutation_datatables_download"T>>',bJQueryUI:!0,bPaginate:!1,bFilter:!0,sScrollY:"600px",bScrollCollapse:!0,oLanguage:{sInfo:"Showing _TOTAL_ mutation(s)",sInfoFiltered:"(out of _MAX_ total mutations)",sInfoEmpty:"No mutations to show"}}},C=jQuery.extend(!0,{},T,t);AdvancedDataTable.call(this,C),C=b._options;var P=b._dispatcher,D=!0,w="",S="",M={},x={};this._initDataTableOpts=o,this._visibilityValue=l,this._searchValue=s,this._addEventListeners=u,this._addHeaderTooltips=m,this.setFilterEventActive=c,this.getManualSearch=p,this.cleanFilters=d,this.requestColumnData=h,this.getCustomData=g,this.getMutations=f,this.getMutationUtil=v,this.getGene=y,this.dispatcher=this._dispatcher}function MutationDiagram(t,e,n,i){var a=this;a.listeners={},a.dispatcher={},_.extend(a.dispatcher,Backbone.Events),a.options=jQuery.extend(!0,{},a.defaultOpts,e),a.dataProxies=i,a.geneSymbol=t,a.data=n,a.pileups=null==n?null:n.pileups,a.highlighted={},a.multiSelect=!1,a.svg=null,a.bounds=null,a.gData=null,a.gLine=null,a.gLabel=null,a.xScale=null,a.yScale=null,a.topLabel=null,a.xAxisLabel=null,a.yAxisLabel=null,a.xMax=null,a.yMax=null,a.maxCount=null,a.mutationColorMap={},a.mutationPileupMap={}}function MutationHistogram(t,e,n){MutationDiagram.call(this,t,e,n)}function MutationPdbPanel(t,e,n,i){function a(t,e,n,i,a){var l=nt;_.each(n,function(n,o){_.each(n,function(n,s){var u=n.chain;if(u.alignments.length>0){var c=e.colors[s%e.colors.length],d=e.marginTop+(a+o)*(e.chainHeight+e.chainPadding),p=r(t,u,c,e,i,d);p.datum(n),at[PdbDataUtil.chainKey(n.pdbId,n.chain.chainId)]=p,null==X&&(X=p),l++}})}),nt=l,o(n,e)}function o(t,e){var i=[],a=[];_.each(t,function(t,e){_.each(t,function(t,e){i.push(t.pdbId),a.push(at[PdbDataUtil.chainKey(t.pdbId,t.chain.chainId)])})}),n.getPdbInfo(i.join(" "),function(t){_.each(a,function(t,n){var i=e.chainTipFn;i(t)})})}function r(t,e,n,i,a,o){for(var r=t.append("g").attr("class","pdb-chain-group").attr("opacity",1),l=i.chainHeight,s=new MergedAlignmentSegmentor(e.mergedAlignment);s.hasNextSegment();){var u=s.getNextSegment(),c=Math.abs(a(u.start)-a(u.end)),d=a(u.start);if(u.type==PdbDataUtil.ALIGNMENT_GAP){var p=r.append("line").attr("stroke",i.chainBorderColor).attr("stroke-width",i.chainBorderWidth).attr("x1",d).attr("y1",o+l/2).attr("x2",d+c).attr("y2",o+l/2);p.datum({initPos:{x:d,y:o+l/2}})}else{var m=r.append("rect").attr("fill",n).attr("opacity",e.mergedAlignment.identityPerc).attr("stroke",i.chainBorderColor).attr("stroke-width",i.chainBorderWidth).attr("x",d).attr("y",o).attr("width",c).attr("height",l);m.datum({initPos:{x:d,y:o}})}}return r}function l(t,e){var n=e.marginLeft-e.labelYPaddingRightV,i=e.marginTop+e.labelYPaddingTopV,a="middle",o="rotate(270, "+n+","+i+")",r="vertical";Z.lengtht){n=i;break}return-1==n&&(n=e.length-1),n}function p(t){var e=0,n=Z.length;return e="auto"!=t?t:K.marginTop+K.marginBottom+n*(K.chainHeight+K.chainPadding)-K.chainPadding/2}function m(t){var e=0,n=Z.length;return e=n>t?K.marginTop+t*(K.chainHeight+K.chainPadding)-K.chainPadding/2:p("auto")}function h(t,e,n){var i=t.append("svg");return i.attr("width",e),i.attr("height",n),i}function f(t){var e=K.elWidth-(K.marginLeft+K.marginRight),n=K.marginLeft;return d3.scale.linear().domain([0,g(t)]).range([n,n+e])}function g(t){var e=[];return _.each(t,function(t){_.each(t,function(t){e.push(t.chain.mergedAlignment.uniprotTo)})}),_.max(e)}function v(){Z=PdbDataUtil.allocateChainRows(e),et=d(Z.length,K.numRows),null==i&&(i=f(Z));var t=$(K.el)[0],n=d3.select(t),o=K.numRows[0];rt=m(o);var r=h(n,K.elWidth,rt);J=r,a(r,K,Z.slice(0,o),i,0),it[0]=!0,0!=K.labelY&&l(r,K),ot=y(Z),C()}function y(t){var e={};return _.each(t,function(t,n){_.each(t,function(t,i){e[PdbDataUtil.chainKey(t.pdbId,t.chain.chainId)]=n})}),e}function b(t,e,n){J.selectAll(t).on(e,n),null==Q[t]&&(Q[t]={}),Q[t][e]=n}function T(t,e){J.selectAll(t).on(e,null),Q[t]&&Q[t][e]&&delete Q[t][e]}function C(){b(".pdb-chain-group","click",function(t,e){L(d3.select(this))})}function P(){_.each(_.keys(Q),function(t){var e=J.selectAll(t);_.each(_.keys(Q[t]),function(n){e.on(n,Q[t][n])})})}function D(){$(K.el).show()}function w(){$(K.el).hide()}function S(t){var e=m(K.numRows[t]),n=J.attr("height");j(e,n),J.transition().duration(K.animationDuration).attr("height",e).each("end",function(){G(e,n)}),rt=e}function M(){var t=x();S(t)}function x(){var t=(tt+1)%(et+1);return it[t]||(a(J,K,Z.slice(K.numRows[tt],K.numRows[t]),i,K.numRows[tt]),P(),it[t]=!0),tt=t,t}function A(t){for(var e=-1,n=tt;t>n&&et>n;n++)e=x();-1!==e&&S(e)}function I(t,e){for(var n=-1,i=ot[PdbDataUtil.chainKey(t,e)],a=0;aK.numRows[0]}function L(t){lt=t;var e=F(t);J.selectAll(".pdb-selection-rectangle-group").remove();var n=J.append("g").attr("class","pdb-selection-rectangle-group").attr("opacity",0),i=n.append("rect").attr("fill","none").attr("stroke",K.highlightBorderColor).attr("stroke-width",K.highlightBorderWidth).attr("x",e.x).attr("y",e.y).attr("width",e.width).attr("height",e.height);n.transition().duration(K.animationDuration).attr("opacity",1),i.datum({initPos:{x:e.x,y:e.y}}),W.trigger(MutationDetailsEvents.PANEL_CHAIN_SELECTED,t)}function F(t){var e=1/0,n=-1,i=-1,a=-1;return t.selectAll("rect").each(function(t,o){var r=d3.select(this);i=parseFloat(r.attr("y")),a=parseFloat(r.attr("height"));var l=parseFloat(r.attr("x")),s=parseFloat(r.attr("width"));e>l&&(e=l),l+s>n&&(n=l+s)}),{x:e,y:i,width:n-e,height:a}}function k(t){null!=lt&&V(lt,t)}function V(t,e){var n=K.animationDuration;N(t,e),t==lt&&N(J.selectAll(".pdb-selection-rectangle-group")),B(t);var i=m(1),a=J.attr("height");j(i,a),J.transition().duration(n).attr("height",i).each("end",function(){G(i,a)})}function N(t,e){var n=K.animationDuration,i=K.marginTop,a=K.chainHeight;t.selectAll("line").transition().duration(n).attr("y1",i+a/2).attr("y2",i+a/2),t.selectAll("rect").transition().duration(n).attr("y",i).each("end",function(){_.isFunction(e)&&e()})}function B(t,e){var n=K.animationDuration,i=t.datum(),a=PdbDataUtil.chainKey(i.pdbId,i.chain.chainId);J.selectAll(".pdb-chain-group").transition().duration(n).attr("opacity",function(t){return PdbDataUtil.chainKey(t.pdbId,t.chain.chainId)===a?1:0}),J.selectAll(".pdb-selection-rectangle-group").transition().duration(n).attr("opacity",function(e){return lt==t?1:0}),J.select(".pdb-panel-y-axis-label-group").transition().duration(n).attr("opacity",0).each("end",function(){_.isFunction(e)&&e()})}function O(t,e,n){J.selectAll(t).transition().duration(n).attr("y1",function(t){return e(this,t,"y1")}).attr("y2",function(t){return e(this,t,"y2")})}function R(t,e,n){J.selectAll(t).transition().duration(n).attr("y",function(t){return e(this,t,"y")})}function U(t){var e=K.animationDuration;q(),z();var n=J.attr("height");j(rt,n),J.transition().duration(e).attr("height",rt).each("end",function(){_.isFunction(t)&&t(),G(rt,n)})}function q(t){var e=K.animationDuration,n=function(t,e,n){return e.initPos.y};R(".pdb-chain-group rect",n,e),O(".pdb-chain-group line",n,e),R(".pdb-selection-rectangle-group rect",n,e),setTimeout(t,e+50)}function z(t){var e=K.animationDuration;J.selectAll(".pdb-chain-group").transition().duration(e).attr("opacity",1),J.selectAll(".pdb-selection-rectangle-group").transition().duration(e).attr("opacity",1), +J.selectAll(".pdb-panel-y-axis-label-group").transition().duration(e).attr("opacity",1).each("end",function(){_.isFunction(t)&&t()})}function H(){return lt}function j(t,e){W.trigger(MutationDetailsEvents.PDB_PANEL_RESIZE_STARTED,t,e,K.maxHeight)}function G(t,e){W.trigger(MutationDetailsEvents.PDB_PANEL_RESIZE_ENDED,t,e,K.maxHeight)}var Y={el:"#mutation_pdb_panel_d3",elWidth:740,elHeight:"auto",maxHeight:200,numRows:[1/0],marginLeft:45,marginRight:30,marginTop:2,marginBottom:0,chainHeight:6,chainPadding:3,labelY:["PDB","Chains"],labelYFont:"sans-serif",labelYFontColor:"#2E3436",labelYFontSize:"12px",labelYFontWeight:"normal",labelYPaddingRightH:45,labelYPaddingTopH:7,labelYPaddingRightV:25,labelYPaddingTopV:20,labelAlignThreshold:5,chainBorderColor:"#666666",chainBorderWidth:.5,highlightBorderColor:"#FF9900",highlightBorderWidth:2,colors:["#3366cc"],animationDuration:1e3,chainTipFn:function(t){var e=t.datum();n.getPdbInfo(e.pdbId,function(n){var i=null;n&&(i=PdbDataUtil.generatePdbInfoSummary(n[e.pdbId],e.chain.chainId));var a=new PdbChainTipView({model:{pdbId:e.pdbId,pdbInfo:i.title,molInfo:i.molecule,chain:e.chain}}),o=a.compileTemplate(),r={content:{text:o},hide:{fixed:!0,delay:100},style:{classes:"qtip-light qtip-rounded qtip-shadow qtip-lightyellow"},position:{my:"bottom left",at:"top center",viewport:$(window)}};cbio.util.addTargetedQTip(t,r)})},yHelpTipFn:function(t){var e=BackboneTemplateCache.getTemplateFn("mutation_details_pdb_help_tip_template"),n=e({}),i={content:{text:n},hide:{fixed:!0,delay:100},style:{classes:"qtip-light qtip-rounded qtip-shadow qtip-lightyellow qtip-wide"},position:{my:"bottom left",at:"top center",viewport:$(window)}};cbio.util.addTargetedQTip(t,i)}},Q={},W={};_.extend(W,Backbone.Events);var K=jQuery.extend(!0,{},Y,t),J=null,Z=null,X=null,tt=0,et=null,nt=0,it=[],at={},ot={},rt=0,lt=null;return{init:v,addListener:b,removeListener:T,getChainGroup:c,getDefaultChainGroup:u,show:D,hide:w,toggleHeight:M,expandToChainLevel:I,minimizeToChain:V,minimizeToHighlighted:k,restoreToFull:U,restoreChainPositions:q,fadeInAll:z,hasMoreChains:E,highlight:L,getHighlighted:H,dispatcher:W}}function MutationPdbTable(t){function e(t,e,n,i,a,o,r,l){var u=DataTableUtil.getColumnOptions(n,a),c={aaData:e,aoColumns:u,aoColumnDefs:[{bVisible:!1,aTargets:o},{bSearchable:!1,aTargets:l}],oColVis:{aiExclude:r},fnDrawCallback:function(t){s._addColumnTooltips()},fnHeaderCallback:function(t,e,n,i,a){$(t).find("th").addClass("mutation-pdb-table-header")},fnRowCallback:function(t,e,n,i){var o=e[a.datum],r=PdbDataUtil.chainKey(o.pdbId,o.chain.chainId);p[r]=t,$(t).addClass("pdb-chain-table-data-row")},fnInitComplete:function(t,e){d.trigger(MutationDetailsEvents.PDB_TABLE_READY)}};return c}function n(t){var e=c.columnVisibility[t],n=e;return e?_.isFunction(e)&&(n=e()):n="hidden",n}function i(t){var e=c.columnSearch[t],n=e;return null==e?n=!1:_.isFunction(e)&&(n=e()),n}function a(){s.getDataTable().fnFilter("")}function o(t,e){var n=PdbDataUtil.chainKey(t,e);r();var i=p[n];$(i).addClass("row_selected"),m=i}function r(){$(c.el).find("tr").removeClass("row_selected")}function l(){return m}var s=this,u={el:"#mutation_pdb_table_d3",elWidth:740,columns:{datum:{sTitle:"datum",tip:""},pdbId:{sTitle:"PDB Id",tip:"",sType:"string"},chain:{sTitle:"Chain",tip:"",sType:"string"},uniprotPos:{sTitle:"Uniprot Positions",tip:"",sType:"numeric"},identityPercent:{sTitle:"Identity Percent",tip:"",sType:"numeric"},organism:{sTitle:"Organism",tip:"",sType:"string"},summary:{sTitle:"Summary",tip:"",sType:"string",sWidth:"65%"}},columnOrder:["datum","pdbId","chain","uniprotPos","identityPercent","organism","summary"],columnVisibility:{pdbId:"visible",chain:"visible",uniprotPos:"visible",identityPercent:"hidden",organism:"visible",summary:"visible",datum:"excluded"},columnSearch:{pdbId:!0,organism:!0,summary:!0},columnRender:{identityPercent:function(t){return Math.round(100*t.chain.mergedAlignment.identityPerc)},pdbId:function(t){var e=BackboneTemplateCache.getTemplateFn("mutation_pdb_table_pdb_cell_template");return e({pdbId:t.pdbId})},chain:function(t){var e=BackboneTemplateCache.getTemplateFn("mutation_pdb_table_chain_cell_template");return e({chainId:t.chain.chainId})},organism:function(t){return t.organism},summary:function(t){var e={summary:t.summary.title,molecule:t.summary.molecule},n=BackboneTemplateCache.getTemplateFn("mutation_pdb_table_summary_cell_template");return n(e)},uniprotPos:function(t){return t.chain.mergedAlignment.uniprotFrom+"-"+t.chain.mergedAlignment.uniprotTo}},columnTooltips:{simple:function(e){MutationViewsUtil.defaultTableTooltipOpts();cbio.util.addTargetedQTip($(e).find(".simple-tip"),t)}},eventListeners:{pdbLink:function(t,e,n){$(t).on("click",".pbd-chain-table-chain-cell a",function(i){i.preventDefault(),r();var a=$(i.target).closest("tr.pdb-chain-table-data-row");a.addClass("row_selected");var o=t.fnGetData(a[0]),l=o[n.datum];e.trigger(MutationDetailsEvents.TABLE_CHAIN_SELECTED,l.pdbId,l.chain.chainId)})}},columnSort:{identityPercent:function(t){return MutationDetailsTableFormatter.assignFloatValue(Math.round(100*t.chain.mergedAlignment.identityPerc))},pdbId:function(t){return t.pdbId},chain:function(t){return t.chain.chainId},organism:function(t){return t.organism},summary:function(t){return t.summary.title+t.summary.molecule},uniprotPos:function(t){return MutationDetailsTableFormatter.assignIntValue(t.chain.mergedAlignment.uniprotFrom)}},columnFilter:{identityPercent:function(t){return Math.round(100*t.chain.mergedAlignment.identityPerc)},summary:function(t){return t.summary.title+" "+t.summary.molecule},uniprotPos:function(t){return t.chain.mergedAlignment.uniprotFrom+"-"+t.chain.mergedAlignment.uniprotTo}},filteringDelay:0,dataTableOpts:{sDom:'<"H"<"mutation_pdb_datatable_info"i><"mutation_pdb_datatable_filter"f>>t',bJQueryUI:!0,bPaginate:!1,bFilter:!0,sScrollY:"200px",bScrollCollapse:!0,oLanguage:{sInfo:"Showing _TOTAL_ PDB chain(s)",sInfoFiltered:"(out of _MAX_ total chains)",sInfoEmpty:"No chains to show"}}},c=jQuery.extend(!0,{},u,t);AdvancedDataTable.call(this,c),c=s._options;var d=s._dispatcher,p={},m=null;this._initDataTableOpts=e,this._visibilityValue=n,this._searchValue=i,this.selectRow=o,this.cleanFilters=a,this.getSelectedRow=l,this.dispatcher=this._dispatcher}function PancanMutationHistogram(t,e,n,i,a){function o(t){return t.map(_.clone)}function r(t){return _.reduce(t,function(t,e){return t[e.cancer_study]=e,t},{})}function l(t){var e=v[t.cancer_study].num_sequenced_samples;return t.num_sequenced_samples=e,t.frequency=t.count/e,t}function s(t){var e=_.reduce(t,function(t,e){return t+e.frequency},0);return-1*e}function u(t){var e=t[0].cancer_type;if(!_.every(t,function(t){return t.cancer_type===e}))throw new Error("not all data in a group have the same cancer type");return e}function c(t){function e(t){return{cancer_study:t,count:0,cancer_type:v[t].cancer_type,num_sequenced_samples:v[t].num_sequenced_samples}}var n=r(t);return _.chain(y).reduce(function(t,e){return _.has(n,e)||t.push(e),t},[]).map(e).value()}function d(t){return t.concat(c(t))}function p(){var t,e=_.find(x[0],function(t){return t.cancer_study===a.this_cancer_study});try{t=e.cancer_type}catch(n){throw new Error(n+": could not find this the corresponding datum for this cancer study, ["+a.this_cancer_study+"]")}var i=function(t){return _.find(t,function(t){return t.cancer_study===a.this_cancer_study})},o=_.zip.apply(null,x);o=_.find(o,i);var r=s(o);L.append("text").text("*").attr("id","star").attr("x",V(a.this_cancer_study)).attr("y",O(-1*r)+10).style("font-family","Helvetica Neue, Helvetica, Arial, sans-serif").style("font-size",3*V.rangeBand()+"px")}function m(t){var e=d3.select(t).selectAll(".mouseOver").data(y).enter().append("rect").attr("class","mouseOver").attr("y",a.margin.top).attr("x",function(t){return V(t)+a.margin.left}).attr("opacity","0").attr("height",E+5).attr("width",V.rangeBand()).on("mouseover",function(){d3.select(this).attr("opacity","0.25")}).on("mouseout",function(){d3.select(this).attr("opacity","0")});e.each(function(t){$(this).qtip({content:{text:"mouseover failed"},position:{my:"left top",at:"center right",viewport:$(window)},style:{classes:"qtip-light qtip-rounded qtip-shadow qtip-wide"},hide:{fixed:!0,delay:100},events:{render:function(e,n){var i=g(t).map(function(t){return t[0].__data__}),a=i.filter(function(t){return _.has(t,"keyword")})[0]||{},o=i.filter(function(t){return!_.has(t,"keyword")})[0]||{},r=o.cancer_study,l=v[r].num_sequenced_samples,s="

"+r+"

"+f(a,o,l);n.set("content.text",s)}}})})}function h(t,e){var n=t.count||0;"frequency"in t||(t.frequency=n/e);var i=(100*t.frequency).toFixed(1)+"%";return _.template("{{percent}} ({{count}} of {{total}} sequenced samples)")({percent:i,count:n,total:e})}function f(t,e,n){return"

"+C+": "+h(t,n)+"

Other "+Y+" mutations: "+h(e,n)+"

"}function g(t){return z.filter(function(e){return e.cancer_study===t})}a=a||{},a=a.sparkline?_.extend({margin:{top:-12,right:0,bottom:0,left:0},width:30,height:12,this_cancer_study:void 0},a):_.extend({margin:{top:6,right:10,bottom:20,left:40},width:600,height:300,this_cancer_study:void 0},a);var v=r(n),y=_.keys(v),b=o(t),T=o(e),C=b[0].hugo+" "+b[0].protein_pos_start;b=d(b).map(function(t){return t.keyword=C,t}),T=d(T);var P={bykeyword:r(b),bygene:r(T)},D=_.intersection(_.keys(P.bykeyword),_.keys(P.bygene));if(b=[],T=[],_.each(D,function(t){b.push(P.bykeyword[t]),T.push(P.bygene[t])}),T.length!==b.length)throw new Error("must be same length");if(T.length!==y.length)throw new Error("there must be a datum for every cancer study and visa versa");T.forEach(function(t){var e=P.bykeyword[t.cancer_study],n=t.count-e.count;if(0>n)throw new Error("more mutations for a particular keyword than for all keywords of a particular gene");t.count=n});var w=_.reduce(T,function(t,e){return t+e.count},0),S=_.reduce(b,function(t,e){return t+e.count},0),M=_.reduce(v,function(t,e){return t+e.num_sequenced_samples},0);_.mixin({unzip:function(t){return _.zip.apply(_,t)}});var x=b.concat(T);try{x=_.chain(x).map(l).groupBy(function(t){return t.cancer_study}).map(_.identity).sortBy(u).unzip().value()}catch(A){throw new Error(A)}var I=a.width-a.margin.left-a.margin.left,E=a.height-a.margin.top-a.margin.bottom,L=d3.select(i).append("svg").attr("width",a.width).attr("height",a.height).append("g").attr("transform","translate("+a.margin.left+","+a.margin.top+")"),F=d3.layout.stack().x(function(t){return t.cancer_study}).y(function(t){return t.frequency}),k=F(x),V=d3.scale.ordinal().domain(x[0].map(function(t){return t.cancer_study})).rangeBands([0,I],.1),N=.2,B=a.sparkline?N:d3.max(k,function(t){return d3.max(t,function(t){return t.y0+t.y})}),O=d3.scale.linear().domain([0,B]).range([E,0]).clamp(!0),R="LimeGreen",U="Green",q=L.selectAll(".layer").data(k).enter().append("g").attr("class","layer").style("fill",function(t,e){return[U,R][e]}),z=q.selectAll("rect").data(function(t){return t}).enter().append("rect").attr("x",function(t){return V(t.cancer_study)}).attr("y",function(t){return O(t.y0+t.y)}).attr("width",function(t){return V.rangeBand()}).attr("height",function(t){return O(t.y0)-O(t.y0+t.y)});if(a.sparkline)return{el:i,qtip:function(){throw new Error("don't qtip a sparkline")}};var H=d3.format(B>.1?".0%":".1%"),j=d3.svg.axis().scale(O).tickFormat(H).orient("left");j.tickSize(j.tickSize(),0,0);var G=function(){function t(t){return{cancer_type:t.cancer_type,start:t.cancer_study,end:t.cancer_study,color:v[t.cancer_study].color}}var e=x[0][0];return _.chain(x[0]).reduce(function(e,n){var i=_.last(e);return i.cancer_type!==n.cancer_type?e.concat(t(n)):i.cancer_type===n.cancer_type?(i.end=n.cancer_study,e):void 0},[t(e)]).value()}();L.selectAll("line").data(G).enter().append("line").attr("x1",function(t){return V(t.start)}).attr("x2",function(t){return V(t.end)+V.rangeBand()}).attr("y1",E+a.margin.bottom/3).attr("y2",E+a.margin.bottom/3).style("stroke-width",5).style("stroke",function(t){return t.color});var Y=(L.append("g").call(j).attr("stroke","#000").attr("shape-rendering","crispEdges"),_.find(k[0],function(t){return void 0!==t.hugo}).hugo),C=_.find(k[0],function(t){return void 0!==t.keyword}).keyword;return _.isUndefined(a.this_cancer_study)||p(),{el:i,qtip:m,overallCountText:function(){return f({count:S},{count:w},M)}}}function MainMutationController(t){function e(){t.diagramView?n(t.diagramView.mutationDiagram):t.dispatcher.on(MutationDetailsEvents.DIAGRAM_INIT,n),t.addResetCallback(i)}function n(t){s=t,t.dispatcher.on(MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED,o),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_DESELECTED,r),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_SELECTED,l),t.dispatcher.on(MutationDetailsEvents.DIAGRAM_PLOT_UPDATED,a)}function i(e){s&&s.resetPlot(),t.hideFilterInfo()}function a(){s&&s.isFiltered()?t.showFilterInfo():t.hideFilterInfo()}function o(){s&&!s.isFiltered()&&t.hideFilterInfo()}function r(t,e){s&&0==s.getSelectedElements().length&&o()}function l(e,n){t.showFilterInfo()}var s=null;e()}function Mutation3dController(t,e,n,i,a,o,r){function l(){e.diagramView?s(e.diagramView.mutationDiagram):e.dispatcher.on(MutationDetailsEvents.DIAGRAM_INIT,s),e.tableView&&e.tableView.mutationTable&&(e.tableView.mutationTable.dispatcher.on(MutationDetailsEvents.PDB_LINK_CLICKED,L),e.tableView.mutationTable.dispatcher.on(MutationDetailsEvents.PROTEIN_CHANGE_LINK_CLICKED,E)),i.addInitCallback(p),t.dispatcher.on(MutationDetailsEvents.GENE_TAB_SELECTED,c),n?u(n):t.dispatcher.on(MutationDetailsEvents.VIS_3D_PANEL_CREATED,u)}function s(t){z=t,t.dispatcher.on(MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED,S),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_DESELECTED,M),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_SELECTED,x),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_MOUSEOVER,A),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_MOUSEOUT,I),t.dispatcher.on(MutationDetailsEvents.DIAGRAM_PLOT_UPDATED,w),t.dispatcher.on(MutationDetailsEvents.DIAGRAM_PLOT_RESET,D)}function u(t){t&&(U=t,q=t.options.mut3dVis,U.dispatcher.on(MutationDetailsEvents.VIEW_3D_PANEL_CLOSED,d),U.dispatcher.on(MutationDetailsEvents.VIEW_3D_STRUCTURE_RELOADED,g))}function c(t){U&&(U.resetPanelPosition(),U.hideView())}function d(){$&&$.hideView()}function p(t){B(),null!=U&&(U.resetPanelPosition(),U.maximizeView())}function m(t,e,n){t>n&&$.toggleScrollBar(n)}function h(t,e,n){n>=t&&$.toggleScrollBar(-1),e!=t&&$.scrollToSelected()}function f(t){H&&$.scrollToSelected();var e=t.datum();null!=U&&(U.maximizeView(),U.updateView(r,e.pdbId,e.chain)),H||null==R||(R.resetFilters(),R.selectChain(e.pdbId,e.chain.chainId),R.scrollToSelected()),H=!1}function g(){i.isVisible()&&z&&z.isHighlighted()&&V()}function v(t,e){t&&e&&($.selectChain(t,e),H=!0)}function y(){$.pdbPanel.minimizeToHighlighted()}function b(t,e){t&&e&&$.pdbPanel.minimizeToChain($.pdbPanel.getChainGroup(t,e))}function T(t){null==$&&($=e.initPdbPanelView(t),$.pdbPanel&&($.pdbPanel.dispatcher.on(MutationDetailsEvents.PANEL_CHAIN_SELECTED,f),$.pdbPanel.dispatcher.on(MutationDetailsEvents.PDB_PANEL_RESIZE_STARTED,m),$.pdbPanel.dispatcher.on(MutationDetailsEvents.PDB_PANEL_RESIZE_ENDED,h)),$.addInitCallback(function(e){C(t)}))}function C(t){null==R&&null!=$&&t.length>0&&(R=$.initPdbTableView(t,function(t,e){e.dispatcher.on(MutationDetailsEvents.PDB_TABLE_READY,P),R=t}),R.pdbTable.dispatcher.on(MutationDetailsEvents.TABLE_CHAIN_SELECTED,v),R.pdbTable.dispatcher.on(MutationDetailsEvents.TABLE_CHAIN_MOUSEOUT,y),R.pdbTable.dispatcher.on(MutationDetailsEvents.TABLE_CHAIN_MOUSEOVER,b)),null!=$&&null!=R&&($.toggleTableControls(),R.toggleView())}function P(){if(null!=$){var t=$.getSelectedChain();if(null!=t){var e=t.datum();R.selectChain(e.pdbId,e.chain.chainId),R.scrollToSelected()}}}function D(){U&&U.isVisible()&&U.refreshView()}function w(){U&&U.isVisible()&&U.refreshView()}function S(){U&&U.isVisible()&&(U.resetHighlight(),U.hideResidueWarning())}function M(t,e){z&&z.isHighlighted()?x():S()}function x(t,e){U&&U.isVisible()&&V()}function A(t,e){if(U&&U.isVisible()){var n=k();n.push(t),N(n,!0)}}function I(t,e){M(t,e)}function E(t){var e=F(t);e&&U&&U.isVisible()&&V()}function L(t){var e=F(t);e&&B(e.get("pdbMatch").pdbId,e.get("pdbMatch").chainId)}function F(t){var e=o.getMutationIdMap(),n=e[t];return n&&z&&(z.clearHighlights(),z.highlightMutation(n.get("mutationSid"))),n}function k(){var t=[];return z&&_.each(z.getSelectedElements(),function(e,n){t=t.concat(e.datum())}),t}function V(){var t=k();N(t)}function N(t,e){var n=U.highlightView(t,!0),i=t.length-n;e||(i>0?U.showResidueWarning(i,t.length):U.hideResidueWarning())}function B(e,n){var o=i.model.uniprotId;t.is3dPanelInitialized()||t.init3dPanel();var r=function(t){null==$&&T(t),null!=U&&null!=$&&t.length>0&&(O(),$.showView(),e&&n?$.selectChain(e,n):$.selectDefaultChain(),$.autoCollapse())};a.getPdbData(o,r)}function O(){if(z){var t=function(t,e,n){return z.mutationColorMap[t]};q.updateOptions({mutationColorMapper:t})}}var $=null,R=null,U=null,q=null,z=null,H=!1;l()}function MutationDetailsController(t,e,n,i){function a(){t.dispatcher.on(MutationDetailsEvents.GENE_TAB_SELECTED,r),t.dispatcher.on(MutationDetailsEvents.GENE_TABS_CREATED,l),t.dispatcher.on(MutationDetailsEvents.VIS_3D_PANEL_INIT,o)}function o(t){var e=p.vis3d;if(e){var n={appOptions:{el:t||"#mutation_details"}},i=jQuery.extend(!0,{},n,e),a=new Mutation3dVis("default3dView",i);a.init(),s(a)}}function r(t){null==v[t]&&u(t,d,p)}function l(){t.$el.find(".mutation-3d-container").hide();var e=h.getGeneList();u(e[0],d,p)}function s(e){var n=t.$el.find(".mutation-3d-container");if(e){var i=new Mutation3dVisView({el:n,config:m.mutation3dVis,mut3dVis:e,pdbProxy:g,mutationProxy:h});i.render(),_=i,t.dispatcher.trigger(MutationDetailsEvents.VIS_3D_PANEL_CREATED,i)}else $(n).hide()}function u(i,a,o){var r=function(r,l){var s=h.getMutationUtil(),u={geneSymbol:i,mutationData:l,dataProxies:n,dataManager:e,uniprotId:r.metadata.identifier,sampleArray:a},d=new MainMutationView({el:"#mutation_details_"+cbio.util.safeProperty(i),config:m.mainMutation,model:u});t.dispatcher.trigger(MutationDetailsEvents.MAIN_VIEW_INIT,d),d.render(),v[i].mainMutationView=d,e.addView(i,d),null==l||0==l.length?d.showNoDataInfo():c(d,i,s,r,o)};h.getMutationData(i,function(t){v[i]={},null==t&&(t=[]);var n=h.getMutationUtil().dataFieldCount(i,"uniprotAcc",["NA"]),a=null,o={geneSymbol:i};n.length>0&&(a=n[0].uniprotAcc),a&&(o.uniprotAcc=a),f.getPfamData(o,function(n){if(null==n)return void console.log("[warning] no pfam data found: %o",o);var i=n[0];e.getData("variantAnnotation",{mutations:t},function(t,e){r(i,t.mutations)})})})}function c(n,i,a,o,r){function l(){if(s){f=n.initMutationDiagramView(s,o);var t=null;m&&(t=m.mutationTable);var e=null;d&&(e=n.initMutationInfoView(d),new MutationInfoController(n)),new MutationDiagramController(f.mutationDiagram,t,e,a)}}var s=r.mutationDiagram,u=r.mutationTable,c=r.vis3d,d=r.infoPanel,p=r.mutationSummary,m=null;u&&(m=n.initMutationTableView(u),new MutationDetailsTableController(n,t));var h=null;p&&(h=n.initSummaryView(u));var f=null;if(a.containsProteinChange(i)?l():e.getData("variantAnnotation",{mutations:n.model.mutationData},function(t,e){l()}),new MainMutationController(n),c){var v=n.init3dView(null);new Mutation3dController(t,n,_,v,g,a,i)}}var d=i.data.sampleList,p=i.view,m=i.render,h=n.mutationProxy,f=n.pfamProxy,g=n.pdbProxy,v={},_=null;a(),this.getMainView=function(t){return v[t]},this.get3dVisView=function(){return _},this.getMainViews=function(){return v},this.getDataManager=function(){return e},this.getDataProxies=function(){return n}}function MutationDetailsTableController(t,e){function n(){t.diagramView?i(t.diagramView.mutationDiagram):t.dispatcher.on(MutationDetailsEvents.DIAGRAM_INIT,i),t.infoView?a(t.infoView):t.dispatcher.on(MutationDetailsEvents.INFO_PANEL_INIT,a),e.dispatcher.on(MutationDetailsEvents.GENE_TAB_SELECTED,p)}function i(t){m=t,t.dispatcher.on(MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED,r),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_DESELECTED,l),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_SELECTED,s),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_MOUSEOVER,c),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_MOUSEOUT,d),t.dispatcher.on(MutationDetailsEvents.DIAGRAM_PLOT_RESET,o)}function a(t){t&&t.dispatcher.on(MutationDetailsEvents.INFO_PANEL_MUTATION_TYPE_SELECTED,u)}function o(){t.tableView&&t.tableView.resetFilters()}function r(){t.tableView&&(t.tableView.clearHighlights(),t.tableView.filter(PileupUtil.getPileupMutations(m.pileups)))}function l(e,n){if(t.tableView){t.tableView.clearHighlights();var i=[];m&&_.each(m.getSelectedElements(),function(t,e){i=i.concat(t.datum().mutations)}),i.length>0?t.tableView.filter(i):t.tableView.filter(PileupUtil.getPileupMutations(m.pileups))}}function s(e,n){if(t.tableView){t.tableView.clearHighlights();var i=[];m&&_.each(m.getSelectedElements(),function(t,e){i=i.concat(t.datum().mutations)}),t.tableView.filter(i)}}function u(e){if(null!==t.tableView){var n=t.infoView.currentMapByType[e];_.size(n)>0?t.tableView.filter(n):(n=t.infoView.initialMapByType[e],t.tableView.filter(n),t.tableView.clearSearchBox())}}function c(e,n){t.tableView&&t.tableView.highlight(e.mutations)}function d(e,n){t.tableView&&t.tableView.clearHighlights()}function p(e){if(t.tableView){var n=t.tableView.mutationTable.getDataTable();n.is(":visible")&&n.fnAdjustColumnSizing()}}var m=null;n()}function MutationDiagramController(t,e,n,i){function a(){e&&e.dispatcher.on(MutationDetailsEvents.MUTATION_TABLE_FILTERED,o),n&&n.dispatcher.on(MutationDetailsEvents.INFO_PANEL_MUTATION_TYPE_SELECTED,r)}function o(e){var n=[],i=[];try{i=$(e).DataTable().rows({filter:"applied"}).data()}catch(a){i=$(e).dataTable()._("tr",{filter:"applied"})}if(_.each(i,function(t,e){var i=t[0].mutation;i&&n.push(i)}),null!==t){var o=new MutationCollection(n);t.updatePlot(PileupUtil.convertToPileups(o))}}function r(e){if(null!==t){var i=n.currentMapByType[e];_.size(i)>0?t.updatePlot(PileupUtil.convertToPileups(new MutationCollection(i))):(i=n.initialMapByType[e],t.updatePlot(PileupUtil.convertToPileups(new MutationCollection(i))))}}a()}function MutationInfoController(t){function e(){t.diagramView?n(t.diagramView.mutationDiagram):t.dispatcher.on(MutationDetailsEvents.DIAGRAM_INIT,n)}function n(t){s=t,t.dispatcher.on(MutationDetailsEvents.DIAGRAM_PLOT_RESET,r),t.dispatcher.on(MutationDetailsEvents.DIAGRAM_PLOT_UPDATED,l),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_SELECTED,o),t.dispatcher.on(MutationDetailsEvents.LOLLIPOP_DESELECTED,a),t.dispatcher.on(MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED,i)}function i(){l()}function a(e,n){if(t.infoView){var i=[];s&&_.each(s.getSelectedElements(),function(t,e){i=i.concat(t.datum())}),i.length>0?t.infoView.updateView(PileupUtil.getPileupMutations(i)):l()}}function o(t,e){a(t,e)}function r(){l()}function l(){t.infoView&&t.infoView.updateView(PileupUtil.getPileupMutations(s.pileups))}var s=null;e()}function MutationMapper(t){function e(){o.proxy.mutationProxy.options.geneList=o.data.geneList.join(" ");var t=DataProxyUtil.initDataProxies(o.proxy);o.dataManager=jQuery.extend(!0,{},o.dataManager,{dataProxies:t});var e=new MutationDataManager(o.dataManager),a={mutationProxy:t.mutationProxy},r={el:o.el,config:o.render.mutationDetails,model:a},l=new MutationDetailsView(r);n=l;var s=new MutationDetailsController(l,e,t,o);i=s,l.render()}var n=null,i=null,a={el:"#mutation_details",data:{geneList:[],sampleList:[]},view:{mutationDiagram:{},mutationTable:{},mutationSummary:{},pdbPanel:{},pdbTable:{},infoPanel:{},vis3d:{}},render:{mutationDetails:{init:null,format:null},mainMutation:{},mutation3dVis:{}},proxy:{pfamProxy:{instance:null,instanceClass:PfamDataProxy,options:{data:{}}},variantAnnotationProxy:{instance:null,instanceClass:VariantAnnotationDataProxy,options:{data:{}}},mutationProxy:{instance:null,instanceClass:MutationDataProxy,options:{data:{},params:{},geneList:""}},clinicalProxy:{instance:null,instanceClass:ClinicalDataProxy,options:{data:{}}},pdbProxy:{instance:null,instanceClass:PdbDataProxy,options:{data:{pdbData:{},infoData:{},summaryData:{},positionData:{}},mutationUtil:{}}},pancanProxy:{instance:null,instanceClass:PancanMutationDataProxy,options:{data:{byKeyword:{},byProteinChange:{},byProteinPosition:{},byGeneSymbol:{}}}},mutationAlignerProxy:{instance:null,instanceClass:MutationAlignerDataProxy,options:{data:{}}},portalProxy:{instance:null,instanceClass:PortalDataProxy,options:{data:{}}}},dataManager:{dataFn:{},dataProxies:{}}},o=jQuery.extend(!0,{},a,t);this.init=e,this.getView=function(){return n},this.getController=function(){return i}}var DataTableUtil=function(){function t(t){var e={};return _.each(t,function(t,n){null==e[t]&&(e[t]=n)}),e}function e(t){var e={};return _.each(_.pairs(t),function(t,n){var i=t[0],a=t[1];null!=a.sTitle&&a.sTitle.length>0&&(e[a.sTitle]=i)}),e}function n(t,e){var n={};return _.each(t,function(t,i){null==n[t]&&(_.isFunction(e)?n[t]=e(t):n[t]="hidden")}),n}function i(t,e){var n={};return _.each(t,function(t,i){null==n[t]&&(n[t]=_.isFunction(e)&&e(t))}),n}function a(t,e,n){var i=[];return _.each(t,function(t,a){"visible"!=n[t]&&i.push(e[t])}),i}function o(t,e,n){var i=[];return _.each(t,function(t,a){"excluded"==n[t]&&i.push(e[t])}),i}function r(t,e,n){var i=[];return _.each(t,function(t,a){n[t]===!1&&i.push(e[t])}),i}function l(t,e){var n=[];return _.each(_.pairs(t),function(t){var i=t[0],a=t[1],o=e[i];if(null!=o){var r={fnRender:function(t){var n=t.aData[e.datum];return a(t,n)},aTargets:[o]};n.push(r)}}),n}function s(t,e,n,i,a){var o={};return _.each(_.pairs(e),function(e){var a=e[0],r=e[1],l=n[a],s=i[a],u=t[a],c=function(t){return null!=l?l(t):r(t)};if(null!=u){var d={mData:function(e,n,i){var a=e[t.datum];return"set"===n?null:"display"===n?r(a):"sort"===n?c(a):"filter"===n?null!=s?s(a):c(a):e[u]},aTargets:[u]};o[a]=d}}),_.each(_.pairs(a),function(e){var n=e[0],i=e[1],a=t[n],r={mData:function(e,n,a){return i(e,n,a,t)},aTargets:[a]};o[n]=r}),_.values(o)}function u(t,e){var n=[];return _.each(_.pairs(t),function(t){var i=t[0],a=t[1],o=e[i];o>0&&(n[o]=a)}),n}function c(t){var e=$(t).attr("alt"),n=parseFloat(e);return isNaN(n)&&(n=""),n}function d(t){return-1!=t.indexOf("label")?$(t).find("label").text().trim()||$(t).text().trim():-1}function p(t){return-1!=t.indexOf("label")?parseInt($(t).text()):-1}function m(t){return-1!=t.indexOf("label")?parseFloat($(t).text()):-1}function h(t,e,n,i){return n>=0?i>=0?n==i?0:i>n?-1:1:-1:i>=0?1:t==e?0:e>t?1:-1}function f(t,e,n,i){return n>=0?i>=0?n==i?0:i>n?1:-1:-1:i>=0?1:t==e?0:e>t?-1:1}return{buildColumnIndexMap:t,buildColumnNameMap:e,buildColumnVisMap:n,buildColumnSearchMap:i,getHiddenColumns:a,getExcludedColumns:o,getNonSearchableColumns:r,getColumnOptions:u,getColumnRenderers:l,getColumnData:s,compareSortAsc:h,compareSortDesc:f,getAltTextValue:c,getLabelTextValue:d,getLabelTextIntValue:p,getLabelTextFloatValue:m}}(),MutationViewsUtil=function(){function t(t,e,n,i){var a=new MutationMapper(e),o=!1;return $(t).is(":visible")&&(a.init(),o=!0),$(n).bind("tabsactivate",function(t,e){e.newTab.text().trim().toLowerCase()==i.toLowerCase()&&(o?a.getView().refreshGenesTab():(a.init(),o=!0))}),a}function e(){return{mutationType:r,validationStatus:l,mutationStatus:s,omaScore:u,cna:c}}function n(){return{content:{attr:"alt"},show:{event:"mouseover"},hide:{fixed:!0,delay:100,event:"mouseout"},style:{classes:"mutation-details-tooltip qtip-shadow qtip-light qtip-rounded"},position:{my:"top left",at:"bottom right",viewport:$(window)}}}function i(t){t=t||"images/ajax-loader.gif";var e={loaderImage:t,width:15,height:15},n=BackboneTemplateCache.getTemplateFn("mutation_table_placeholder_template");return n(e)}function a(t,e,n){var i=t.fnGetData();_.each(i,function(i,a){t.fnUpdate(null,a,e[n],!1,!1)}),i.length>0&&t.fnUpdate(null,0,e[n])}var o={missense:{label:"Missense",longName:"Missense",style:"missense_mutation",mainType:"missense",priority:1},inframe:{label:"IF",longName:"In-frame",style:"inframe_mutation",mainType:"inframe",priority:2},truncating:{label:"Truncating",longName:"Truncating",style:"trunc_mutation",mainType:"truncating",priority:4},nonsense:{label:"Nonsense",longName:"Nonsense",style:"trunc_mutation",mainType:"truncating",priority:6},nonstop:{label:"Nonstop",longName:"Nonstop",style:"trunc_mutation",mainType:"truncating",priority:7},nonstart:{label:"Nonstart",longName:"Nonstart",style:"trunc_mutation",mainType:"truncating",priority:8},frameshift:{label:"FS",longName:"Frame Shift",style:"trunc_mutation",mainType:"truncating",priority:4},frame_shift_del:{label:"FS del",longName:"Frame Shift Deletion",style:"trunc_mutation",mainType:"truncating",priority:4},frame_shift_ins:{label:"FS ins",longName:"Frame Shift Insertion",style:"trunc_mutation",mainType:"truncating",priority:5},in_frame_ins:{label:"IF ins",longName:"In-frame Insertion",style:"inframe_mutation",mainType:"inframe",priority:3},in_frame_del:{label:"IF del",longName:"In-frame Deletion",style:"inframe_mutation",mainType:"inframe",priority:2},splice_site:{label:"Splice",longName:"Splice site",style:"trunc_mutation",mainType:"truncating",priority:9},fusion:{label:"Fusion",longName:"Fusion",style:"fusion",mainType:"other",priority:10},other:{style:"other_mutation",mainType:"other",priority:11}},r={missense_mutation:o.missense,missense:o.missense,missense_variant:o.missense,frame_shift_ins:o.frame_shift_ins,frame_shift_del:o.frame_shift_del,frameshift:o.frameshift,frameshift_deletion:o.frame_shift_del,frameshift_insertion:o.frame_shift_ins,de_novo_start_outofframe:o.frameshift,frameshift_variant:o.frameshift,nonsense_mutation:o.nonsense,nonsense:o.nonsense,stopgain_snv:o.nonsense,splice_site:o.splice_site,splice:o.splice_site,"splice site":o.splice_site,splicing:o.splice_site,splice_site_snp:o.splice_site,splice_site_del:o.splice_site,splice_site_indel:o.splice_site,translation_start_site:o.nonstart,start_codon_snp:o.nonstart,start_codon_del:o.nonstart,nonstop_mutation:o.nonstop,in_frame_del:o.in_frame_del,in_frame_ins:o.in_frame_ins,indel:o.in_frame_del,nonframeshift_deletion:o.inframe,nonframeshift:o.inframe,"nonframeshift insertion":o.inframe,nonframeshift_insertion:o.inframe,targeted_region:o.inframe,inframe:o.inframe,truncating:o.truncating,fusion:o.fusion,other:o.other},l={valid:{label:"V",style:"valid",tooltip:"Valid"},validated:{label:"V",style:"valid",tooltip:"Valid"},wildtype:{label:"W",style:"wildtype",tooltip:"Wildtype"},unknown:{label:"U",style:"unknown",tooltip:"Unknown"},not_tested:{label:"U",style:"unknown",tooltip:"Unknown"},none:{label:"U",style:"unknown",tooltip:"Unknown"},na:{label:"U",style:"unknown",tooltip:"Unknown"}},s={somatic:{label:"S",style:"somatic",tooltip:"Somatic"},germline:{label:"G",style:"germline",tooltip:"Germline"},unknown:{label:"U",style:"unknown",tooltip:"Unknown"},none:{label:"U",style:"unknown",tooltip:"Unknown"},na:{label:"U",style:"unknown",tooltip:"Unknown"}},u={h:{label:"High",style:"oma_high",tooltip:"High"},m:{label:"Medium",style:"oma_medium",tooltip:"Medium"},l:{label:"Low",style:"oma_low",tooltip:"Low"},n:{label:"Neutral",style:"oma_neutral",tooltip:"Neutral"}},c={"-2":{label:"DeepDel",style:"cna-homdel",tooltip:"Deep deletion"},"-1":{label:"ShallowDel",style:"cna-hetloss",tooltip:"Shallow deletion"},0:{label:"Diploid",style:"cna-diploid",tooltip:"Diploid / normal"},1:{label:"Gain",style:"cna-gain",tooltip:"Low-level gain"},2:{label:"AMP",style:"cna-amp",tooltip:"High-level amplification"},unknown:{label:"NA",style:"cna-unknown",tooltip:"CNA data is not available for this gene"}};return{initMutationMapper:t,renderTablePlaceHolder:i,refreshTableColumn:a,defaultTableTooltipOpts:n,getVisualStyleMaps:e}}(),MutationDetailsTableFormatter=function(){function t(t){return e(E,t)}function e(t,e){var n,i,a;return null!=t[e]?(n=t[e].style, +i=t[e].label,a=t[e].tooltip):(n=t.unknown.style,i=t.unknown.label,a=t.unknown.tooltip),{style:n,tip:a,text:i}}function n(t){var e=16,n=t,i="",a=t;return null!=t&&t.length>e+2&&(n=t.substring(0,e)+"...",i="simple-tip"),{style:i,tip:a,text:n}}function i(t){return a(M,t)}function a(t,e){var n,i;return null!=e&&(e=e.toLowerCase()),null!=t[e]?(n=t[e].style,i=t[e].label):(n=t.other.style,i=e),{style:n,text:i}}function o(t){return r(A,t)}function r(t,e){var n="simple-tip",i=e,a="";return null!=e&&(e=e.toLowerCase()),null!=t[e]&&(n=t[e].style,i=t[e].label,a=t[e].tooltip),{style:n,tip:a,text:i}}function l(t){return s(x,t)}function s(t,e){var n,i,a;return null!=e&&(e=e.toLowerCase()),null!=t[e]?(n=t[e].style,i=t[e].label,a=t[e].tooltip):(n=t.unknown.style,i=t.unknown.label,a=t.unknown.tooltip),{style:n,tip:a,text:i}}function u(t,e){return c(I,t,e)}function c(t,e,n){var i="",a="",o="",r="";return null!=e&&(e=e.toLowerCase()),null!=t[e]&&(r=t[e].tooltip,null!=n&&(r=n.toFixed(2)),i=t[e].label,a=t[e].style,o="oma_link"),{fisClass:a,omaClass:o,value:r,text:i}}function d(t,e,n,i){var a="NA",o=e+n,r="",l="";return t&&(r="mutation_table_allele_freq",a=t.toFixed(2),l=i),{text:a,total:o,style:r,tipClass:l}}function p(t){return h(t.get("pdbMatch"))}function m(t){return h(t.get("igvLink"))}function h(t){return t?"#":""}function f(t){var e="mutation-table-protein-change",n="click to highlight the position on the diagram",i="";return null!=t.get("aminoAcidChange")&&t.get("aminoAcidChange").length>0&&"NA"!==t.get("aminoAcidChange")&&null!=t.get("cancerStudyShort")&&-1!=t.get("cancerStudyShort").toLowerCase().indexOf("msk-impact")&&g(t.get("proteinChange"),t.get("aminoAcidChange"))&&(i="The original annotation file indicates a different value: "+v(t.get("aminoAcidChange"))+""),{text:v(t.get("proteinChange")),style:e,tip:n,additionalTip:i}}function g(t,e){var n=!1;if(t=v(t),e=v(e),e!==t){var i=t.match(/[A-Z]/g),a=e.match(/[A-Z]/g),o=t.match(/[0-9]+/),r=e.match(/[0-9]+/),l=t.match(/([a-z]+)/),s=e.match(/([a-z]+)/);o&&r&&o.length>0&&r.length>0&&o[0]!=r[0]?n=!0:i&&a&&i.length>0&&a.length>0&&"X"!==i[0]&&"X"!==a[0]&&i[0]!==a[0]?n=!0:i&&a&&i.length>1&&a.length>1&&i[1]!==a[1]?n=!0:l&&s&&l.length>0&&s.length>0&&l[0]!==s[0]&&(n=!0)}return n}function v(t){var e="p.";return-1!=t.indexOf(e)&&(t=t.substr(t.indexOf(e)+e.length)),t}function _(t){var e="tumor_type",n="";return{text:t.get("tumorType"),style:e,tip:n}}function y(t){var e="",n="";return t>0&&(e="mutation_table_cosmic",n=t),{style:e,count:n}}function b(t){var e="",n="";return t>0&&(e="mutation_table_cbio_portal",n=t),{style:e,frequency:n}}function T(t){var e=t,n="mutation_table_int_value";return null==t&&(e="NA",n=""),{text:e,style:n}}function C(t){var e=t,n="mutation_table_allele_count";return null==t&&(e="NA",n=""),{text:e,style:n}}function P(t,e){var n;return null!=t&&(t=t.toLowerCase()),n="low"==t||"l"==t?2:"medium"==t||"m"==t?3:"high"==t||"h"==t?4:"neutral"==t||"n"==t?1:-1,n>0&&!isNaN(e)&&(n+=e/1e3),n}function D(t){var e=parseInt(t);return isNaN(e)&&(e=-(1/0)),e}function w(t){var e=parseFloat(t);return isNaN(e)&&(e=-(1/0)),e}var S=MutationViewsUtil.getVisualStyleMaps(),M=S.mutationType,x=S.validationStatus,A=S.mutationStatus,I=S.omaScore,E=S.cna;return{getCaseId:n,getProteinChange:f,getPdbMatchLink:p,getIgvLink:m,getAlleleCount:C,getAlleleFreq:d,getCNA:t,getMutationType:i,getMutationStatus:o,getValidationStatus:l,getFis:u,getTumorType:_,getCosmic:y,getCbioPortal:b,getIntValue:T,assignValueToPredictedImpact:P,assignIntValue:D,assignFloatValue:w}}(),PileupUtil=function(){function t(t){var e=t.mutations,n={};return _.each(e,function(t){var e=t.get("mutationType")||"";e=e.trim().toLowerCase(),void 0==n[e]&&(n[e]=[]),n[e].push(t)}),n}function e(e){var n=t(e),i=[];return _.each(_.keys(n),function(t){i.push({type:t,count:n[t].length})}),i.sort(function(t,e){return e.count-t.count}),i}function n(e){var n=MutationViewsUtil.getVisualStyleMaps().mutationType,i=t(e),a=[],o={};return _.each(_.keys(i),function(t){var e=void 0;null!=n[t]&&(e=n[t].mainType),void 0==e&&(e=n.other.mainType),void 0==o[e]&&(o[e]=0),o[e]+=i[t].length}),_.each(_.keys(o),function(t){a.push({type:t,count:o[t],priority:n[t].priority})}),a.sort(function(t,e){return e.count===t.count?e.priority-t.priority:e.count-t.count}),a}function i(){return c++,"pileup_"+c}function a(t){var e={};return _.each(t,function(t){_.each(t.mutations,function(n){e[n.get("mutationSid")]=t.pileupId})}),e}function o(t){t=r(t);for(var e={},n=0;n0&&(e[t.get("proteinChange")]=t.get("proteinChange"))});var n=_.keys(e).sort(),i="";n.length>1&&(i=cbio.util.lcss(n[0],n[n.length-1]));var a=i;return _.each(n,function(t){a+=t.substring(i.length)+"/"}),a.substring(0,a.length-1)}function s(t){var e=0;return _.each(t,function(t){e+=t.count}),e}function u(t){var e=[];return _.each(t,function(t){e=e.concat(t.get("mutations")||[])}),e}var c=0;return{nextId:i,mapToMutations:a,convertToPileups:o,countMutations:s,getPileupMutations:u,getMutationTypeMap:t,groupMutationsByType:e,groupMutationsByMainType:n}}(),BackboneTemplateCache=function(){function t(t){return _.template($("#"+t).html())}function e(e){var i=n[e];return null==i&&(i=t(e),n[e]=i),i}var n={};return{getTemplateFn:e}}(),DataProxyUtil=function(){function t(t){var n={};return _.each(_.keys(t).sort(),function(i){var a=t[i],o=null;o="pdbProxy"==i?e(a,function(t){var e=n.mutationProxy;return null!=e&&e.hasData()?(t.options.mutationUtil=e.getMutationUtil(),!0):!1}):e(a),n[i]=o}),n}function e(t,e){var n=t.instance;if(null==n){if(null!=e&&_.isFunction(e)&&!e(t))return null;var i=t.instanceClass;n=new i(t.options),n.init()}return n}return{initDataProxies:t,initDataProxy:e}}();JmolScriptGenerator.prototype=new MolScriptGenerator,JmolScriptGenerator.prototype.constructor=JmolScriptGenerator,Mol3DScriptGenerator.prototype=new MolScriptGenerator,Mol3DScriptGenerator.prototype.constructor=Mol3DScriptGenerator;var MutationDetailsUtil=function(t){var e="germline",n="valid",i={},a={},o={},r={},l={},s={},u=[];this.getMutationGeneMap=function(){return i},this.getMutationCaseMap=function(){return a},this.getMutationIdMap=function(){return o},this.getMutations=function(){return u},this.processMutationData=function(t){i=this._updateGeneMap(t),a=this._updateCaseMap(t),o=this._updateIdMap(t),r=this._updateKeywordMap(t),l=this._updateProteinChangeMap(t),s=this._updateProteinPosStartMap(t),u=u.concat(t.models)},this.getProteinPositions=function(t){var e=i[t],n=[];if(null!=e)for(var a=0;a0&&(void 0!==t.numGermlineCases&&t.numGermlineCases>0&&(i=t.numGermlineCases),e=t.numGermline/i*100,n+="Germline Mutation Rate: "+e.toFixed(1)+"%, "),e=t.numSomatic/t.numCases*100,n+="Somatic Mutation Rate: "+e.toFixed(1)+"%]"},this.countMutations=function(t,n){for(var i=n.length,o=0,r=0,l=0,s=0;s0})},this.containsRefAllele=function(t){return this._contains(t,function(t){return t.get("referenceAllele")&&"NA"!=t.get("referenceAllele")})},this.containsVarAllele=function(t){return this._contains(t,function(t){return t.get("variantAllele")&&"NA"!=t.get("variantAllele")})},this.containsEndPos=function(t){return this._contains(t,function(t){return t.get("endPos")&&t.get("endPos")>0})},this.containsFis=function(t){return this._contains(t,function(t){return t.get("functionalImpactScore")&&"NA"!=t.get("functionalImpactScore")})},this.containsCosmic=function(t){return this._contains(t,function(t){return t.get("cosmic")&&t.getCosmicCount()&&t.getCosmicCount()>0})},this.containsMutationType=function(t){return this._contains(t,function(t){return t.get("mutationType")&&"NA"!=t.get("mutationType")})},this.containsMutationCount=function(t){return this._contains(t,function(t){return t.get("mutationCount")&&t.get("mutationCount")>0})},this.containsKeyword=function(t){return this._contains(t,function(t){return t.get("keyword")&&"NA"!=t.get("keyword")})},this.containsMutationEventId=function(t){return this._contains(t,function(t){return t.get("mutationEventId")&&"NA"!=t.get("mutationEventId")})},this.distinctTumorTypeCount=function(t){t=t.toUpperCase();var e=i[t],n={};if(null!=e)for(var a=0;ae.pdbId?-1:1),n});var e=null,n=[],i={};return _.each(t,function(t,n){e=new PdbAlignmentModel(t),void 0==i[e.pdbId]&&(i[e.pdbId]={}),void 0==i[e.pdbId][e.chain]&&(i[e.pdbId][e.chain]=[]),i[e.pdbId][e.chain].push(e)}),_.each(_.keys(i),function(t){var e=[];_.each(_.keys(i[t]),function(n){var a=new PdbChainModel({chainId:n,alignments:i[t][n]});e.push(a)});var a=new PdbModel({pdbId:t,chains:e});n.push(a)}),new PdbCollection(n)}function e(t){var e=[],n=t.midlineAlign,i=t.uniprotAlign,a=t.pdbAlign;if(n.length===i.length&&n.length===a.length)for(var o=0;o0?(i+=t[0].alignmentString,a=t[0].uniprotTo,e=t[0],_.each(t,function(t,n){var o=t.uniprotFrom-a-1,r=t.alignmentString;if(0==o)i+=r;else if(o>0){for(var l=[],s=0;o>s;s++)l.push(C);l.push(r),i+=l.join("")}else{var u=[],c=Math.min(-1*o,r.length);u.push(i.substr(i.length+o,c)),u.push(r.substr(0,c)),u[0]!=u[1]&&(console.log("[warning] alignment mismatch: "+e.alignmentId+" & "+t.alignmentId),console.log(u[0]),console.log(u[1])),i+=r.substr(-1*o)}a=Math.max(a,t.uniprotTo),a==t.uniprotTo&&(e=t)}),n.uniprotFrom=t[0].uniprotFrom,n.uniprotTo=n.uniprotFrom+i.length,n.pdbFrom=t[0].pdbFrom,n.mergedString=i,n.identityPerc=u(i),n.identity=c(i),n):n}function r(t,e){var n=null,i=t.getProteinStartPos(),a=t.get("mutationType")||"";if(a=a.trim().toLowerCase(),null==i||"fusion"===a)return n;for(var o=0;o=c.uniprotFrom&&i<=c.uniprotTo;if(d&&s(c,i)){n={pdbId:u.pdbId,chainId:u.chain.chainId};break}}if(n)break}return n}function l(t,e){return e?(_.each(t,function(t,n){if(null==t)return void console.log("warning [processMutationData]: mutation (at index %d) is null.",n);var i=PdbDataUtil.mutationToPdb(t,e);t.set({pdbMatch:i})}),t):t}function s(t,e){var n=e-t.uniprotFrom,i=t.mergedString[n],a=i==C;return!a}function u(t){for(var e=0,n=0,i=0;i0){for(var a=!1,o=0;o0&&n[0].sort(function(t,e){return e.chain.mergedAlignment.mergedString.length-t.chain.mergedAlignment.mergedString.length}),n}function p(t,e){var n=!0;return(t.mergedAlignment.uniprotFrom>=e.mergedAlignment.uniprotTo||e.mergedAlignment.uniprotFrom>=t.mergedAlignment.uniprotTo)&&(n=!1),n}function m(t){var e=[];return t.each(function(t,n){t.chains.each(function(n,i){var a={pdbId:t.pdbId,chain:n};e.push(a)})}),h(e,[g,y,v,b,T]),e}function h(t,e){t.sort(function(t,n){for(var i=0,a=0;at.pdbId?-1:e.pdbIdt.chain.chainId?-1:e.chain.chainId0&&(r=r.substring(n.length),l=l.substring(n.length),t+=n.length,e+=n.length,a=t.toString(),o=e.toString())}}var n=void 0,i=t.chr,a=t.startPos,o=t.endPos,r=t.referenceAllele,l=t.variantAllele;return _.isFunction(t.get)&&(i=t.get("chr"),a=t.get("startPos"),o=t.get("endPos"),r=t.get("referenceAllele"),l=t.get("variantAllele")),null!=r&&r===l&&console.log("[VariantAnnotationUtil.generateVariantKey] Warning: Reference allele ("+r+") for "+i+":"+a+"-"+o+" is the same as variant allele"),i&&a&&r&&l&&(e(),n=i+":g."+a+r+">"+l,o&&("-"===r||0===r.length?n=i+":g."+o+"_"+a+"ins"+l:("-"===l||0===l.length)&&(n=i+":g."+a+"_"+o+"del"+r))),n}return{generateVariantKey:i,addAnnotationData:t}}(),VepParser=function(){function t(t){var i={};if(!t)return console.log("[warning] VEP parser error"),{};if(t.error)return console.log("[warning] VEP parser error: "+t.error),{};var o=t.allele_string,l=o.split("/",-1);2===l.length&&(i.referenceAllele=l[0],i.variantType=a(l[0],l[1])),i.ncbiBuildNo=t.assembly_name,i.chr=t.seq_region_name,i.startPos=t.start,i.endPos=t.end,i.strand=r(t.strand);var s=t.transcript_consequences,u=t.most_severe_consequence;i.transcripts=[],_.each(s,function(t,n){i.transcripts.push(e(t,u,i.variantType))});var c=n(s,u);return c&&i.transcripts[c.index]&&(i.canonicalTranscript=i.transcripts[c.index]),i.rawData=t,i}function e(t,e,n,i){i=i||{},i.geneSymbol=t.gene_symbol;var a=t.consequence_terms;if(null!=a&&a.length>0){var r=o(a[0]);"Frame_Shift"===r&&(null!=n&&"INS"===n?r+="_Ins":"DEL"===n&&(r+="_Del")),i.variantClassification=r}var s=t.refseq_transcript_ids;null!=s&&s.length>0&&(i.refseqIds=s);var u=t.hgvsc;null!=u&&(i.hgvsc=u.substr(u.indexOf(":")+1));var c=t.hgvsp;null!=c&&(i.hgvsp=c.substr(c.indexOf(":")+1)),i.transcriptId=t.transcript_id,i.proteinPosStart=t.protein_start,i.proteinPosEnd=t.protein_end,i.codons=t.codons;var d;if(null!=c&&(d=c.substr(c.indexOf(":")+1),_.each(_.pairs(l),function(t,e){d=d.replace(new RegExp(t[0],"g"),t[1])}),i.hgvspShort=d),("splice_acceptor_variant"===e||"splice_donor_variant"===e)&&i.hgvsc){var p=/c\.([0-9]+)*/.exec(i.hgvsc);if(p&&2==p.length){var m=parseInt(p[1]);1>m&&(m=1);var h=m+m%3/3;i.hgvspShort="p.X"+h+"_splice"}}return"synonymous_variant"===e&&(d="p."+t.amino_acids+t.protein_start+t.amino_acids,i.hgvspShort=d),i.mutationType=i.variantClassification,i.proteinChange=i.hgvspShort,i.refseqIds&&i.refseqIds.length>0&&(i.refseqMrnaId=i.refseqIds[0]),i}function n(t,e){var n=[];return _.each(t,function(t,e){1==t.canonical&&n.push({index:e,transcript:t})}),1===n.length?n[0]:n.length>1?i(n,e):(_.each(t,function(t,e){n.push({index:e,transcript:t})}),i(n,e))}function i(t,e){var n=null;return _.each(t,function(t,i){var a=t.transcript.consequence_terms;null==n&&null!=a&&null!=e&&_.each(a,function(i,a){i.trim().toLowerCase()===e.trim().toLowerCase()&&(n=t)})}),n}function a(t,e){var n=t.length,i=e.length;if(n="-"===t?0:n,i="-"===e?0:i,n===i){var a=["SNP","DNP","TNP"];return 3>n?a[n-1]:"ONP"}return i>n?"INS":"DEL"}function o(t){return s[t.toLowerCase()]}function r(t){var e;return e=null==t||"+"===t||"-"===t?t:0>t?"-":t>0?"+":t}var l={Ala:"A",Arg:"R",Asn:"N",Asp:"D",Asx:"B",Cys:"C",Glu:"E",Gln:"Q",Glx:"Z",Gly:"G",His:"H",Ile:"I",Leu:"L",Lys:"K",Met:"M",Phe:"F",Pro:"P",Ser:"S",Thr:"T",Trp:"W",Tyr:"Y",Val:"V",Xxx:"X",Ter:"*"},s={splice_acceptor_variant:"Splice_Site",splice_donor_variant:"Splice_Site",transcript_ablation:"Splice_Site",stop_gained:"Nonsense_Mutation",frameshift_variant:"Frame_Shift",stop_lost:"Nonstop_Mutation",initiator_codon_variant:"Translation_Start_Site",start_lost:"Translation_Start_Site",inframe_insertion:"In_Frame_Ins",inframe_deletion:"In_Frame_Del",missense_variant:"Missense_Mutation",protein_altering_variant:"Missense_Mutation",coding_sequence_variant:"Missense_Mutation",conservative_missense_variant:"Missense_Mutation",rare_amino_acid_variant:"Missense_Mutation",transcript_amplification:"Intron",splice_region_variant:"Intron",intron_variant:"Intron",INTRAGENIC:"Intron",intragenic_variant:"Intron",incomplete_terminal_codon_variant:"Silent",synonymous_variant:"Silent",stop_retained_variant:"Silent",NMD_transcript_variant:"Silent",mature_miRNA_variant:"RNA",non_coding_exon_variant:"RNA",non_coding_transcript_exon_variant:"RNA",non_coding_transcript_variant:"RNA",nc_transcript_variant:"RNA","5_prime_UTR_variant":"5'UTR","5_prime_UTR_premature_start_codon_gain_variant":"5'UTR","3_prime_UTR_variant":"3'UTR",TF_binding_site_variant:"IGR",regulatory_region_variant:"IGR",regulatory_region:"IGR",intergenic_variant:"IGR",intergenic_region:"IGR",upstream_gene_variant:"5'Flank",downstream_gene_variant:"3'Flank",TFBS_ablation:"Targeted_Region",TFBS_amplification:"Targeted_Region",regulatory_region_ablation:"Targeted_Region",regulatory_region_amplification:"Targeted_Region",feature_elongation:"Targeted_Region",feature_truncation:"Targeted_Region"};return{parseJSON:t}}(),MutationModel=Backbone.Model.extend({_initialize:function(t){this.mutationId=t.mutationId,this.mutationSid=t.mutationSid,this.geneticProfileId=t.geneticProfileId,this.mutationEventId=t.mutationEventId,this.caseId=t.caseId,this.geneSymbol=t.geneSymbol,this.linkToPatientView=t.linkToPatientView,this.cancerType=t.cancerType,this.cancerStudy=t.cancerStudy,this.cancerStudyShort=t.cancerStudyShort,this.cancerStudyLink=t.cancerStudyLink,this.tumorType=t.tumorType,this.proteinChange=t.proteinChange,this.aminoAcidChange=t.aminoAcidChange,this.mutationType=t.mutationType,this.cosmic=t.cosmic,this.cosmicCount=this.calcCosmicCount(t.cosmic),this.functionalImpactScore=t.functionalImpactScore,this.fisValue=t.fisValue,this.msaLink=t.msaLink,this.xVarLink=t.xVarLink,this.pdbLink=t.pdbLink,this.pdbMatch=t.pdbMatch,this.igvLink=t.igvLink,this.mutationStatus=t.mutationStatus,this.validationStatus=t.validationStatus,this.sequencingCenter=t.sequencingCenter,this.ncbiBuildNo=t.ncbiBuildNo,this.chr=t.chr,this.startPos=t.startPos,this.endPos=t.endPos,this.referenceAllele=t.referenceAllele,this.variantAllele=t.variantAllele,this.tumorFreq=t.tumorFreq,this.normalFreq=t.normalFreq,this.tumorRefCount=t.tumorRefCount,this.tumorAltCount=t.tumorAltCount,this.normalRefCount=t.normalRefCount,this.normalAltCount=t.normalAltCount,this.canonicalTranscript=t.canonicalTranscript,this.refseqMrnaId=t.refseqMrnaId,this.codonChange=t.codonChange,this.uniprotId=t.uniprotId,this.uniprotAcc=t.uniprotAcc,this.proteinPosStart=t.proteinPosStart,this.proteinPosEnd=t.proteinPosEnd,this.mutationCount=t.mutationCount,this.specialGeneData=t.specialGeneData,this.keyword=t.keyword,this.cna=t.cna,this.myCancerGenome=t.myCancerGenome,this.isHotspot=t.isHotspot},url:function(){},getProteinStartPos:function(){var t=this.get("proteinPosStart");return(null==t||0==t.length||"NA"==t||0>t)&&(t=this.getProteinChangeLocation()),t},getProteinChangeLocation:function(){var t=null,e=null,n=this.get("proteinChange");return null!=n&&(e=n.match(/[0-9]+/)),e&&e.length>0&&(t=e[0]),t},getCosmicCount:function(){if(this.get("cosmicCount"))return this.get("cosmicCount");if(this.get("cosmic")){var t=this.calcCosmicCount(this.get("cosmic"));return this.set({cosmicCount:t}),t}return null},calcCosmicCount:function(t){var e=0;return t&&t.forEach(function(t){e+=t[2]}),e}}),MutationCollection=Backbone.Collection.extend({model:MutationModel,initialize:function(t){},parse:function(t){},url:function(){}}),PdbAlignmentModel=Backbone.Model.extend({initialize:function(t){this.alignmentId=t.alignmentId,this.pdbId=t.pdbId,this.chain=t.chain,this.uniprotId=t.uniprotId,this.pdbFrom=t.pdbFrom,this.pdbTo=t.pdbTo,this.uniprotFrom=t.uniprotFrom,this.uniprotTo=t.uniprotTo,this.alignmentString=t.alignmentString||PdbDataUtil.alignmentString(t),this.eValue=t.eValue,this.identityPerc=t.identityPerc}}),PdbAlignmentCollection=Backbone.Collection.extend({model:PdbAlignmentModel,initialize:function(t){}}),PdbChainModel=Backbone.Model.extend({initialize:function(t){this.chainId=t.chainId,this.positionMap=t.positionMap,this.alignments=new PdbAlignmentCollection(t.alignments),this.mergedAlignment=PdbDataUtil.mergeAlignments(t.alignments)}}),PdbChainCollection=Backbone.Collection.extend({model:PdbChainModel,initialize:function(t){}}),PdbModel=Backbone.Model.extend({initialize:function(t){this.pdbId=t.pdbId,this.chains=new PdbChainCollection(t.chains)}}),PdbCollection=Backbone.Collection.extend({model:PdbModel,initialize:function(t){}}),Pileup=Backbone.Model.extend({initialize:function(t){this.pileupId=t.pileupId,this.mutations=t.mutations,this.count=t.count,this.location=t.location,this.label=t.label,this.stats=t.stats}}),CosmicTipView=Backbone.View.extend({render:function(){var t=this.compileTemplate();this.$el.html(t),this.format()},format:function(){this.$el.find(".cosmic-details-table").dataTable({aaSorting:[[2,"desc"]],sDom:"pt",aoColumnDefs:[{mRender:function(t,e,n){return''+t+""},aTargets:[0]},{sType:"aa-change-col",sClass:"left-align-td",aTargets:[1]},{sType:"numeric",sClass:"left-align-td",aTargets:[2]}],bDestroy:!1,bPaginate:!0,bJQueryUI:!0,bFilter:!1})},_parseCosmic:function(t){var e=[];return t.forEach(function(t){e.push(t[0]+""+t[1]+""+t[2])}),""+e.join("")+""},compileTemplate:function(){var t=this._parseCosmic(this.model.cosmic),e={cosmicDataRows:t,cosmicTotal:this.model.total,mutationKeyword:this.model.keyword},n=BackboneTemplateCache.getTemplateFn("mutation_details_cosmic_tip_template");return n(e)}}),LollipopTipStatsView=Backbone.View.extend({initialize:function(){},render:function(){var t=BackboneTemplateCache.getTemplateFn("mutation_details_lollipop_tip_stats_template"),e=this.$el.find("table tbody");return _.each(this.model,function(n){e.append(t(n))}),this}}),LollipopTipView=Backbone.View.extend({render:function(){var t=this.compileTemplate();this.$el.html(t),this.format()},format:function(){},showStats:!1,setShowStats:function(t){this.showStats=t},getShowStats:function(t){return this.showStats},compileTemplate:function(){var t=this.model,e=t.count>1?"mutations":"mutation",n={count:t.count,mutationStr:e,label:t.label},i=BackboneTemplateCache.getTemplateFn("mutation_details_lollipop_tip_template"),a=$(i(n)),o=a.find(".lollipop-stats");return this.showStats?(new LollipopTipStatsView({el:o,model:t.stats}).render(),o.find("table").dataTable({sDom:"t",bJQueryUI:!0,bDestroy:!0,aaSorting:[[1,"desc"]],aoColumns:[{bSortable:!1},{bSortable:!1}]})):o.hide(),a.html()}}),MainMutationView=Backbone.View.extend({initialize:function(t){var e={config:{loaderImage:"images/ajax-loader.gif"}};this.options=jQuery.extend(!0,{},e,t),this.dispatcher={},_.extend(this.dispatcher,Backbone.Events)},render:function(){var t=this,e={geneSymbol:t.model.geneSymbol,uniprotId:t.model.uniprotId},n=BackboneTemplateCache.getTemplateFn("mutation_view_template"),i=n(e);t.$el.html(i),t.format()},format:function(){var t=this;t.$el.find(".mutation-details-filter-info").hide(),t.$el.find(".mutation-details-no-data-info").hide(),t.$el.find(".mutation-3d-initializer").hide(),t.$el.find(".mutation-info-panel-container").hide(),t.$el.find(".mutation-summary-view").hide(),t.$el.find(".mutation-table-container").hide(),t.$el.find(".mutation-diagram-view").hide()},initPdbPanelView:function(t){var e=this,n=null;e.diagramView&&e.diagramView.mutationDiagram&&(n=e.diagramView.mutationDiagram);var i={el:e.$el.find(".mutation-pdb-panel-view"),config:{loaderImage:e.options.config.loaderImage},model:{geneSymbol:e.model.geneSymbol,pdbColl:t,pdbProxy:e.model.dataProxies.pdbProxy},diagram:n},a=new PdbPanelView(i);return a.render(),e._pdbPanelView=a,a},initSummaryView:function(){var t=this,e=t.$el.find(".mutation-summary-view");e.show();var n={el:e,model:{mutationProxy:t.model.dataProxies.mutationProxy,clinicalProxy:t.model.dataProxies.clinicalProxy,geneSymbol:t.model.geneSymbol,sampleArray:t.model.sampleArray}},i=new MutationSummaryView(n);return i.render(),t.summaryView=i,i},init3dView:function(t){var e=this;return e._init3dView(e.model.geneSymbol,e.model.uniprotId,e.model.dataProxies.pdbProxy,t)},_init3dView:function(t,e,n,i){var a=this,o=a.$el.find(".mutation-3d-initializer");o.show();var r=new Mutation3dView({el:o,model:{uniprotId:e,geneSymbol:t,pdbProxy:n}});return r.render(),i&&i.isVisible()&&r.resetView(),r},initMutationDiagramView:function(t,e){var n=this;return n.diagramView=n._initMutationDiagramView(n.model.geneSymbol,n.model.mutationData,e,n.model.dataProxies,t),n.diagramView?n.dispatcher.trigger(MutationDetailsEvents.DIAGRAM_INIT,n.diagramView.mutationDiagram):console.log("Error initializing mutation diagram: %s",n.model.geneSymbol),n.diagramView},_initMutationDiagramView:function(t,e,n,i,a){var o=this,r=o.$el.find(".mutation-diagram-view");r.show();var l={mutations:e,sequence:n,geneSymbol:t,dataProxies:i,diagramOpts:a},s=new MutationDiagramView({el:r,model:l});return s.render(),s},initMutationTableView:function(t){var e=this;return e.tableView=e._initMutationTableView(e.model.geneSymbol,e.model.mutationData,e.model.dataProxies,e.model.dataManager,t),e.tableView||console.log("Error initializing mutation table: %s",e.model.geneSymbol),e.tableView},_initMutationTableView:function(t,e,n,i,a){var o=this,r=o.$el.find(".mutation-table-container");r.show();var l=new MutationDetailsTableView({el:r,config:{loaderImage:o.options.config.loaderImage},model:{geneSymbol:t,mutations:e,dataProxies:n,dataManager:i,tableOpts:a}});return l.render(),l},initMutationInfoView:function(t){var e=this,n=e.$el.find(".mutation-info-panel-container");n.show();var i={mutations:e.model.mutationData,infoPanelOpts:t},a=new MutationInfoPanelView({el:n,model:i});return a.render(),e.infoView=a,e.dispatcher.trigger(MutationDetailsEvents.INFO_PANEL_INIT,e.infoView), +a},addResetCallback:function(t){var e=this,n=e.$el.find(".mutation-details-filter-reset");n.click(t)},showFilterInfo:function(){this.$el.find(".mutation-details-filter-info").slideDown()},hideFilterInfo:function(){this.$el.find(".mutation-details-filter-info").slideUp()},showNoDataInfo:function(){this.$el.find(".mutation-details-no-data-info").slideDown()},hideNoDataInfo:function(){this.$el.find(".mutation-details-no-data-info").slideUp()}}),Mutation3dView=Backbone.View.extend({initialize:function(t){this.options=t||{},this.dispatcher={},_.extend(this.dispatcher,Backbone.Events)},render:function(){var t=this,e=(t.model.geneSymbol,BackboneTemplateCache.getTemplateFn("mutation_3d_view_template")),n=e({});this.$el.html(n),this.format()},format:function(){var t=this,e=t.$el.find(".mutation-3d-vis");e.attr("disabled","disabled");var n=function(n){if(n)e.removeAttr("disabled");else{var i=t.model.geneSymbol,a="No structure data for "+i,o={content:{text:a},hide:{fixed:!0,delay:100,event:"mouseout"},show:{event:"mouseover"},style:{classes:"qtip-light qtip-rounded qtip-shadow cc-ui-tooltip"},position:{my:"bottom center",at:"top center",viewport:$(window)}};t.$el.qtip(o)}},i=t.model.pdbProxy,a=t.model.uniprotId;i.hasPdbData(a,n)},addInitCallback:function(t){var e=this,n=e.$el.find(".mutation-3d-vis");n.click(t)},resetView:function(){var t=this,e=t.$el.find(".mutation-3d-vis");e.click()},isVisible:function(){var t=this;return t.$el.is(":visible")}}),Mutation3dVisInfoView=Backbone.View.extend({render:function(){var t=this,e=BackboneTemplateCache.getTemplateFn("mutation_3d_vis_info_template"),n=e(t.model);t.$el.html(n),t.format()},format:function(){var t=this,e=t.model.pdbInfo,n=t.model.molInfo;null==e||0==e.length?t.$el.find(".mutation-3d-pdb-info").hide():t._addExpander(".mutation-3d-pdb-info"),null==n||0==n.length?t.$el.find(".mutation-3d-mol-info").hide():t._addExpander(".mutation-3d-mol-info")},_addExpander:function(t){var e=this,n={slicePoint:40,widow:2,expandPrefix:" ",expandText:"[...]",userCollapseText:"[^]",moreClass:"expander-read-more",lessClass:"expander-read-less",detailClass:"expander-details",expandEffect:"fadeIn",collapseEffect:"fadeOut"};e.$el.find(t).expander(n)}}),Mutation3dVisView=Backbone.View.extend({initialize:function(t){var e={config:{loaderImage:"images/ajax-loader.gif",helpImage:"images/help.png"}};this.options=jQuery.extend(!0,{},e,t),this.dispatcher={},_.extend(this.dispatcher,Backbone.Events)},render:function(){var t=this,e=BackboneTemplateCache.getTemplateFn("mutation_3d_vis_template"),n=e({loaderImage:t.options.config.loaderImage,helpImage:t.options.config.helpImage});t.$el.html(n),t.format()},format:function(){var t=this,e=t.options.mut3dVis,n=t.$el;n.hide(),t.hideResidueWarning(),t.hideNoMapWarning();var i=t.$el.find(".mutation-3d-vis-help-content"),a=BackboneTemplateCache.getTemplateFn("3Dmol_basic_interaction");i.html(a({})),i.hide(),null!=e&&e.updateContainer(n),t.$el.find(".mutation-3d-close").click(function(){t.hideView()}),t.$el.find(".mutation-3d-minimize").click(function(){null!=e&&e.toggleSize()}),t._initMutationControls(),t._initProteinControls(),t._initButtons(),n.draggable({handle:".mutation-3d-info-title",stop:function(t,e){var i=parseInt(n.css("top")),a=parseInt(n.css("left"));0>i&&n.css("top",0),0>a&&n.css("left",0)}}),n.resizable({alsoResize:".mutation-3d-vis-container,.mutation-3d-vis-container div:eq(0)",handles:"sw, s, w",minWidth:400,minHeight:300,start:function(t,e){n.find(".mutation-3d-vis-help-content").css("width","auto"),n.css("position","fixed")},stop:function(t,e){n.css("height","auto"),n.css("position","fixed")},resize:function(t,n){t.stopPropagation(),e.resizeViewer()}}).on("resize",function(t){t.stopPropagation()})},_initButtons:function(){var t=this,e=t.options.mut3dVis,n=t.$el.find(".mutation-3d-vis-help-content"),i=t.$el.find(".mutation-3d-vis-help-init"),a=t.$el.find(".mutation-3d-vis-help-open"),o=t.$el.find(".mutation-3d-vis-help-close"),r=t.$el.find(".mutation-3d-pymol-dload");a.click(function(t){t.preventDefault(),n.slideToggle(),i.slideToggle()}),o.click(function(t){t.preventDefault(),n.slideToggle(),i.slideToggle()}),r.click(function(n){n.preventDefault();var i=e.generatePymolScript(),a=t.$el.find(".mutation-3d-pdb-id").text().trim()+"_"+t.$el.find(".mutation-3d-chain-id").text().trim()+".pml",o={filename:a,contentType:"text/plain;charset=utf-8",preProcess:!1};cbio.download.initDownload(i,o)}),r.qtip(t._generateTooltipOpts("Download PyMOL script"))},_initMutationControls:function(){var t=this,e=t.options.mut3dVis,n=t.$el.find(".mutation-3d-side-chain-select");n.change(function(){var t=$(this).val();e&&(e.updateOptions({displaySideChain:t}),e.reapplyStyle())});var i=t.$el.find(".mutation-3d-mutation-color-select");i.change(function(){var t=$(this).val();e&&(e.updateOptions({colorMutations:t}),e.reapplyStyle())}),t._initMutationColorInfo(),t._initSideChainInfo()},_initProteinControls:function(){var t=this,e=t.options.mut3dVis,n=t.$el.find(".mutation-3d-display-non-protein");n.change(function(){var t=n.is(":checked");e&&(e.updateOptions({restrictProtein:!t}),e.reapplyStyle())}),t._initHideNonProteinInfo(),t._initProteinSchemeSelector(),t._initProteinColorSelector()},_initProteinColorSelector:function(){var t=this,e=t.$el.find(".mutation-3d-protein-color-select"),n=t.options.mut3dVis;e.change(function(){var t=$(this).val();n.updateOptions({colorProteins:t}),n.reapplyStyle()})},_initProteinSchemeSelector:function(){var t=this,e=t.options.mut3dVis,n=t.$el.find(".mutation-3d-protein-style-select"),i=t.$el.find(".mutation-3d-protein-color-select");t._initProteinColorInfo(),n.change(function(){var t=$(this).val(),n=!1;i.find("option").removeAttr("disabled");var a=[];if("spaceFilling"==t?(a.push(i.find("option[value='bySecondaryStructure']")),a.push(i.find("option[value='byChain']"))):a.push(i.find("option[value='byAtomType']")),_.each(a,function(t,e){t.is(":selected")&&(t.removeAttr("selected"),i.find("option[value='uniform']").attr("selected","selected"),n="uniform"),t.attr("disabled","disabled")}),e){var o={};o.proteinScheme=t,n&&(o.colorProteins=n),e.updateOptions(o),e.reapplyStyle()}})},_initZoomSlider:function(){var t=this,e=t.$el.find(".mutation-3d-zoom-slider"),n=t.options.mut3dVis,i=function(t){return 0>t?100+t:100+5*t},a=function(t,e){n&&n.zoomTo(i(e.value))};e.slider({value:0,min:-80,max:80,stop:a,slide:a})},updateView:function(t,e,n){var i=this,a=i.options.mut3dVis,o=i.options.pdbProxy,r=function(t){n.positionMap=t,a.show(),i.refreshView(e,n),i.pdbId=e,i.chain=n},l=function(a){var l={pdbId:e,chainId:n.chainId,pdbInfo:"",molInfo:""};if(a&&a[e]){var s=PdbDataUtil.generatePdbInfoSummary(a[e],n.chainId);l.pdbInfo=s.title,l.molInfo=s.molecule}var u=new Mutation3dVisInfoView({el:i.$el.find(".mutation-3d-info"),model:l});u.render(),o.getPositionMap(t,n,r)};o.getPdbInfo(e,l)},refreshView:function(t,e){var n=this,i=n.options.mut3dVis;n.hideResidueWarning(),n.hideNoMapWarning();var a=function(t){0==t.length?n.showNoMapWarning():n.hideNoMapWarning()};if(null==t&&null==e||t==n.pdbId&&e==n.chain){var o=i.refresh();a(o),n.dispatcher.trigger(MutationDetailsEvents.VIEW_3D_STRUCTURE_RELOADED)}else n.showLoader(),setTimeout(function(){var o=i.reload(t,e,function(){n.hideLoader(),n.dispatcher.trigger(MutationDetailsEvents.VIEW_3D_STRUCTURE_RELOADED)});a(o)},50)},_initMutationColorInfo:function(){var t=this,e=t.$el.find(".mutation-type-color-help"),n=BackboneTemplateCache.getTemplateFn("mutation_3d_type_color_tip_template"),i=n({}),a=t._generateTooltipOpts(i);a.style.classes+=" qtip-wide",e.qtip(a)},_initProteinColorInfo:function(){var t=this,e=t.$el.find(".protein-struct-color-help"),n=BackboneTemplateCache.getTemplateFn("mutation_3d_structure_color_tip_template"),i=n({}),a=t._generateTooltipOpts(i);a.style.classes+=" qtip-wide",e.qtip(a)},_initSideChainInfo:function(){var t=this,e=t.$el.find(".display-side-chain-help"),n=BackboneTemplateCache.getTemplateFn("mutation_3d_side_chain_tip_template"),i=n({}),a=t._generateTooltipOpts(i);e.qtip(a)},_initHideNonProteinInfo:function(){var t=this,e=t.$el.find(".display-non-protein-help"),n=BackboneTemplateCache.getTemplateFn("mutation_3d_non_protein_tip_template"),i=n({}),a=t._generateTooltipOpts(i);e.qtip(a)},_generateTooltipOpts:function(t){return{content:{text:t},hide:{fixed:!0,delay:100,event:"mouseout"},show:{event:"mouseover"},style:{classes:"qtip-light qtip-rounded qtip-shadow"},position:{my:"top right",at:"bottom center",viewport:$(window)}}},minimizeView:function(){var t=this,e=t.options.mut3dVis;e&&e.minimize()},maximizeView:function(){var t=this,e=t.options.mut3dVis;e&&e.maximize()},resetPanelPosition:function(){var t=this,e=t.$el;e.css({left:"",position:"",top:0})},hideView:function(){var t=this,e=t.options.mut3dVis;null!=e&&e.hide(),t.dispatcher.trigger(MutationDetailsEvents.VIEW_3D_PANEL_CLOSED)},isVisible:function(){var t=this,e=t.options.mut3dVis;return e.isVisible()},focusView:function(t){var e=this,n=e.options.mut3dVis;return t?n.focusOn(t):(n.resetFocus(),!0)},highlightView:function(t,e){var n=this,i=n.options.mut3dVis;return i.highlight(t,e)},resetHighlight:function(){var t=this,e=t.options.mut3dVis;e.resetHighlight()},showLoader:function(){var t=this,e=t.$el.find(".mutation-3d-vis-loader"),n=t.$el.find(".mutation-3d-vis-container"),i=n.css("height");0!==i&&"0px"!==i&&(t._actualHeight=i,n.css("height",0)),e.show()},hideLoader:function(){var t=this,e=t.$el.find(".mutation-3d-vis-loader"),n=t.$el.find(".mutation-3d-vis-container");e.hide(),n.css("height",t._actualHeight)},showResidueWarning:function(t,e){var n=this,i=n.$el.find(".mutation-3d-residue-warning"),a=n.$el.find(".mutation-3d-unmapped-info");n.$el.find(".mutation-3d-nomap-warning").is(":visible")||(e>1?a.text(t+" of the selections"):a.text("Selected mutation"),i.show())},hideResidueWarning:function(){var t=this,e=t.$el.find(".mutation-3d-residue-warning");e.hide()},showNoMapWarning:function(){var t=this,e=t.$el.find(".mutation-3d-nomap-warning");e.show()},hideNoMapWarning:function(){var t=this,e=t.$el.find(".mutation-3d-nomap-warning");e.hide()}}),MutationCustomizePanelView=Backbone.View.extend({initialize:function(t){this.options=t||{}},render:function(){var t=this,e=t.options.diagram,n={minY:2,maxY:e.getInitialMaxY()},i=BackboneTemplateCache.getTemplateFn("mutation_customize_panel_template"),a=i(n);t.$el.html(a),t.format()},format:function(){var t=this,e=t.options.diagram;t.$el.hide();var n=t.$el.find(".diagram-customize-close"),i=t.$el.find(".diagram-y-axis-slider"),a=t.$el.find(".diagram-y-axis-limit-input");n.click(function(e){e.preventDefault(),t.toggleView()}),a.val(e.getMaxY()),i.slider({value:e.getMaxY(),min:2,max:e.getInitialMaxY(),change:function(t,n){var i=n.value;return i>e.getThreshold()?(i=e.getThreshold(),void $(this).slider("value",i)):(a.val(i),e.updateOptions({maxLengthY:i}),void e.rescaleYAxis())},slide:function(t,e){a.val(e.value)}}),a.keypress(function(t){var n=13;if(t.keyCode==n){var o=a.val(),r=o;isNaN(r)||r>e.getThreshold()?r=e.getThreshold():2>o&&(r=2),a.val(r),i.slider("option","value",Math.floor(r))}})},toggleView:function(){var t=this;t.$el.slideToggle()}}),MutationDetailsTableView=Backbone.View.extend({initialize:function(t){var e={config:{loaderImage:"images/ajax-loader.gif"}};this.options=jQuery.extend(!0,{},e,t),this.dispatcher={},_.extend(this.dispatcher,Backbone.Events)},render:function(){var t=this,e=BackboneTemplateCache.getTemplateFn("mutation_details_table_template"),n=e({loaderImage:t.options.config.loaderImage});t.$el.html(n),t._initMutationTable(),t.format()},_initMutationTable:function(t){var e=this,n=jQuery.extend(!0,{},e.model.tableOpts);n.el=n.el||e.$el.find(".mutation_details_table");var i=new MutationCollection(e.model.mutations),a=new MutationDetailsUtil(i),o=new MutationDetailsTable(n,e.model.geneSymbol,a,e.model.dataProxies,e.model.dataManager);return e.mutationTable=o,_.isFunction(t)&&t(e,o),e._generateRowData(o,o.getColumnOptions(),i,function(t){o.renderTable(t)}),o},_generateRowData:function(t,e,n,i){var a=[];n.each(function(n){for(var i={table:t,mutation:n},o=[i],r=0;r<_.size(e)-1;r++)o.push(null);a.push(o)}),i(a)},format:function(){},hideView:function(){var t=this;t.$el.hide()},showView:function(){var t=this;t.$el.show()},highlight:function(t){for(var e=this,n=e.$el.find(".mutation_details_table"),i=0;i0){var o=e.countMutations(n,i);a=e.generateSummary(o)}return a},_germlineMutationSummary:function(t){var e=this,n=e.model.mutationProxy.getMutationUtil(),i=e.model.geneSymbol,a=e.model.sampleArray,o=0,r="";if(a.length>0){for(var l=n.countMutations(i,a),s=0;s0)&&(i.pdbInfo=": "+e),(null!=n||n.length>0)&&(i.molInfo=": "+n);var a=BackboneTemplateCache.getTemplateFn("mutation_details_pdb_chain_tip_template");return a(i)}}),PdbPanelView=Backbone.View.extend({initialize:function(t){var e={config:{loaderImage:"images/ajax-loader.gif"}};this.options=jQuery.extend(!0,{},e,t),this.collapseTimer=null,this.expandTimer=null},render:function(){var t=this,e=BackboneTemplateCache.getTemplateFn("pdb_panel_view_template"),n=e({});t.$el.html(n),t.pdbPanel=t._initPdbPanel(),t.format()},format:function(){var t=this;t.$el.hide();var e=t.$el.find(".expand-collapse-pdb-panel"),n=t.$el.find(".init-pdb-table"),i=t.$el.find(".pdb-table-controls"),a=t.$el.find(".triangle-down"),o=t.$el.find(".triangle");t.pdbPanel.hasMoreChains()&&(e.button({icons:{primary:"ui-icon-triangle-2-n-s"},text:!1}),e.css({width:"300px",height:"12px"}),e.click(function(){t.pdbPanel.toggleHeight()})),e.hide(),i.hide(),a.hide(),o.click(function(t){n.click()}),t.$el.find(".mutation-pdb-main-container").mouseenter(function(e){t.autoExpand()}),t.$el.find(".mutation-pdb-main-container").mouseleave(function(e){t.autoCollapse()})},hideView:function(){var t=this;t.$el.slideUp()},showView:function(){var t=this;t.$el.slideDown()},initPdbTableView:function(t,e){var n=this,i={el:n.$el.find(".mutation-pdb-table-view"),config:{loaderImage:n.options.config.loaderImage},model:{geneSymbol:n.model.geneSymbol,pdbColl:t,pdbProxy:n.model.pdbProxy}},a=new PdbTableView(i);return n.pdbTableView=a,a.render(e),a},addInitCallback:function(t){var e=this,n=e.$el.find(".init-pdb-table");n.click(function(e){e.preventDefault(),t(e)})},toggleTableControls:function(){var t=this;t.$el.find(".triangle").toggle()},selectDefaultChain:function(){var t=this,e=t.pdbPanel,n=e.getDefaultChainGroup();t.clearTimers(),e.restoreChainPositions(function(){e.highlight(n)})},selectChain:function(t,e){var n=this,i=n.pdbPanel;n.clearTimers(),i.restoreChainPositions(function(){i.expandToChainLevel(t,e);var n=i.getChainGroup(t,e);n&&i.highlight(n)})},getSelectedChain:function(){var t=this,e=t.pdbPanel;return e.getHighlighted()},autoCollapse:function(t){null==t&&(t=2e3);var e=this,n=e.$el.find(".expand-collapse-pdb-panel"),i=e.$el.find(".pdb-table-controls"),a=e.$el.find(".pdb-table-wrapper");e.clearTimers(),e.collapseTimer=setTimeout(function(){e.pdbPanel.minimizeToHighlighted(),n.slideUp(),i.slideUp(),a.slideUp()},t)},autoExpand:function(t){null==t&&(t=400);var e=this,n=e.$el.find(".expand-collapse-pdb-panel"),i=e.$el.find(".pdb-table-controls"),a=e.$el.find(".pdb-table-wrapper");e.clearTimers(),e.expandTimer=setTimeout(function(){e.pdbPanel.restoreToFull(),e.pdbPanel.hasMoreChains()&&n.slideDown(),i.slideDown(),a.slideDown(),null!=e.pdbTableView&&e.pdbTableView.refreshView()},t)},toggleScrollBar:function(t){var e=this,n=e.$el.find(".mutation-pdb-panel-container");t>0?(n.css("max-height",t),n.css("overflow",""),n.css("overflow-y","scroll")):(n.css("max-height",""),n.css("overflow-y",""),n.css("overflow","hidden"))},scrollToSelected:function(){var t=this,e=t.$el.find(".mutation-pdb-panel-container");e.scrollTo($(".pdb-selection-rectangle-group"),{axis:"y",duration:800,offset:-150})},clearTimers:function(){var t=this;null!=t.collapseTimer&&clearTimeout(t.collapseTimer),null!=t.expandTimer&&clearTimeout(t.expandTimer)},_initPdbPanel:function(){var t=this,e=t.model.pdbColl,n=t.model.pdbProxy,i=t.options.diagram,a={el:t.$el.find(".mutation-pdb-panel-container"),maxHeight:200},o=null;null!=i&&(o=i.xScale,a.marginLeft=i.options.marginLeft,a.marginRight=i.options.marginRight);var r=new MutationPdbPanel(a,e,n,o);return r.init(),r}}),PdbTableView=Backbone.View.extend({initialize:function(t){var e={config:{loaderImage:"images/ajax-loader.gif"}};this.options=jQuery.extend(!0,{},e,t)},render:function(t){var e=this,n=BackboneTemplateCache.getTemplateFn("pdb_table_view_template"),i=n({loaderImage:e.options.config.loaderImage});e.$el.html(i),e._initPdbTable(t),e.format()},format:function(){var t=this;t.$el.hide()},hideView:function(){var t=this;t.$el.slideUp()},showView:function(){var t=this;t.$el.slideDown()},toggleView:function(){var t=this;t.$el.slideToggle()},refreshView:function(){var t=this;t.pdbTable.getDataTable().fnAdjustColumnSizing()},resetFilters:function(){var t=this;t.pdbTable.cleanFilters()},selectChain:function(t,e){var n=this;null!=n.pdbTable&&n.pdbTable.selectRow(t,e)},scrollToSelected:function(){var t=this,e=t.pdbTable.getSelectedRow(),n=t.$el.find(".dataTables_scrollBody");n.scrollTo($(e),{axis:"y",duration:800})},_initPdbTable:function(t){var e=this,n=e.model.pdbColl,i=e.model.pdbProxy,a=jQuery.extend(!0,{},e.model.tableOpts);a.el=a.el||e.$el.find(".pdb-chain-table");var o=new MutationPdbTable(a);return e.pdbTable=o,_.isFunction(t)&&t(e,o),e._generateRowData(o.getColumnOptions(),n,i,function(t){o.renderTable(t),e.$el.find(".pdb-chain-table-loader").hide()}),o},_generateRowData:function(t,e,n,i){var a=[],o=[];e.each(function(t){o.push(t.pdbId)}),n.getPdbInfo(o.join(" "),function(n){e.each(function(e){e.chains.each(function(i){for(var o={pdbId:e.pdbId,chain:i,organism:PdbDataUtil.getOrganism(n[e.pdbId],i.chainId),summary:PdbDataUtil.generatePdbInfoSummary(n[e.pdbId],i.chainId)},r=[o],l=0;l<_.size(t)-1;l++)r.push(null);a.push(r)})}),i(a)})}}),PredictedImpactTipView=Backbone.View.extend({render:function(){var t=this.compileTemplate();this.$el.html(t),this.format()},format:function(){var t=function(t){var e=!0;return(null==t||"NA"==t||0==t.length)&&(e=!1),e},e=this.model.xvia;t(e)||this.$el.find(".mutation-assessor-main-link").hide();var n=this.model.pdbLink;t(n)||this.$el.find(".mutation-assessor-3d-link").hide();var i=this.model.msaLink;t(i)||this.$el.find(".mutation-assessor-msa-link").hide()},compileTemplate:function(){var t={linkOut:this.model.xvia,msaLink:this.model.msaLink,pdbLink:this.model.pdbLink,impact:this.model.impact},e=BackboneTemplateCache.getTemplateFn("mutation_details_fis_tip_template");return e(t)}}),RegionTipView=Backbone.View.extend({render:function(){var t=this.compileTemplate();this.$el.html(t),this.format()},format:function(){},compileTemplate:function(){var t={identifier:this.model.identifier,type:this.model.type.toLowerCase(),description:this.model.description,start:this.model.start,end:this.model.end,pfamAccession:this.model.pfamAccession,mutationAlignerInfo:this.model.mutationAlignerInfo},e=BackboneTemplateCache.getTemplateFn("mutation_details_region_tip_template");return e(t)}});ClinicalDataProxy.prototype=new AbstractDataProxy,ClinicalDataProxy.prototype.constructor=ClinicalDataProxy,MutationAlignerDataProxy.prototype=new AbstractDataProxy,MutationAlignerDataProxy.prototype.constructor=MutationAlignerDataProxy,MutationDataProxy.prototype=new AbstractDataProxy,MutationDataProxy.prototype.constructor=MutationDataProxy,PancanMutationDataProxy.prototype=new AbstractDataProxy,PancanMutationDataProxy.prototype.constructor=PancanMutationDataProxy,PdbDataProxy.prototype=new AbstractDataProxy,PdbDataProxy.prototype.constructor=PdbDataProxy,PfamDataProxy.prototype=new AbstractDataProxy,PfamDataProxy.prototype.constructor=PfamDataProxy,PortalDataProxy.prototype=new AbstractDataProxy,PortalDataProxy.prototype.constructor=PortalDataProxy,VariantAnnotationDataProxy.prototype=new AbstractDataProxy,VariantAnnotationDataProxy.prototype.constructor=VariantAnnotationDataProxy,MutationDetailsTable.prototype=new AdvancedDataTable,MutationDetailsTable.prototype.constructor=MutationDetailsTable,MutationDiagram.prototype.defaultOpts={el:"#mutation_diagram_d3",elWidth:740,elHeight:180,marginLeft:45,marginRight:30,marginTop:30,marginBottom:60,labelTop:"",labelTopFont:"sans-serif",labelTopFontColor:"#2E3436",labelTopFontSize:"12px",labelTopFontWeight:"bold",labelTopMargin:2,labelX:!1,labelXFont:"sans-serif",labelXFontColor:"#2E3436",labelXFontSize:"12px",labelXFontWeight:"normal",labelY:"# Mutations",labelYFont:"sans-serif",labelYFontColor:"#2E3436",labelYFontSize:"12px",labelYFontWeight:"normal",minLengthX:0,minLengthY:5,maxLengthX:1/0,maxLengthY:1/0,seqFillColor:"#BABDB6",seqHeight:14,seqPadding:5,regionHeight:24,regionFont:"sans-serif",regionFontColor:"#FFFFFF",regionFontSize:"12px",regionTextAnchor:"middle",showRegionText:!0,showStats:!1,multiSelectKeycode:16,lollipopLabelCount:1,lollipopLabelThreshold:2,lollipopFont:"sans-serif",lollipopFontColor:"#2E3436",lollipopFontSize:"10px",lollipopTextAnchor:"auto",lollipopTextPadding:8,lollipopTextAngle:0,lollipopFillColor:{missense:"#008000",truncating:"#000000",inframe:"#8B4513",fusion:"#8B00C9",other:"#8B00C9","default":"#BB0000"},lollipopBorderColor:"#BABDB6",lollipopBorderWidth:.5,lollipopSize:30,lollipopHighlightSize:100,lollipopStrokeWidth:1,lollipopStrokeColor:"#BABDB6",lollipopShapeRegular:"circle",lollipopShapeSpecial:"circle",xAxisPadding:10,xAxisTickIntervals:[100,200,400,500,1e3,2e3,5e3,1e4,2e4,5e4],xAxisTicks:8,xAxisTickSize:6,xAxisStroke:"#AAAAAA",xAxisFont:"sans-serif",xAxisFontSize:"10px",xAxisFontColor:"#2E3436",yAxisPadding:5,yAxisLabelPadding:15,yAxisTicks:10,yAxisTickIntervals:[1,2,5,10,20,50,100,200,500],yAxisTickSize:6,yAxisStroke:"#AAAAAA",yAxisFont:"sans-serif",yAxisFontSize:"10px",yAxisFontColor:"#2E3436",yAxisAutoAdjust:!0,animationDuration:1e3,fadeDuration:1500,lollipopTipFn:function(t,e,n){ +var i=new LollipopTipView({model:e});i.setShowStats(n);var a=i.compileTemplate(),o={content:{text:a},hide:{fixed:!0,delay:100,event:"mouseout"},show:{event:"mouseover"},style:{classes:"qtip-light qtip-rounded qtip-shadow cc-ui-tooltip"},position:{my:"bottom left",at:"top center",viewport:$(window)}};cbio.util.addTargetedQTip(t,o)},regionTipFn:function(t,e,n){var i={identifier:e.metadata.identifier,type:e.type,description:e.metadata.description,start:e.metadata.start,end:e.metadata.end,pfamAccession:e.metadata.accession,mutationAlignerInfo:""};n.getMutationAlignerData({pfamAccession:e.metadata.accession},function(e){if(null!=e&&null!=e.linkToMutationAligner&&e.linkToMutationAligner.length>0){var n=BackboneTemplateCache.getTemplateFn("mutation_aligner_info_template");i.mutationAlignerInfo=n({linkToMutationAligner:e.linkToMutationAligner})}var a=new RegionTipView({model:i}),o=a.compileTemplate(),r={content:{text:o},hide:{fixed:!0,delay:100,event:"mouseout"},show:{event:"mouseover"},style:{classes:"qtip-light qtip-rounded qtip-shadow qtip-lightyellow"},position:{my:"bottom left",at:"top center",viewport:$(window)}};cbio.util.addTargetedQTip(t,r)})}},MutationDiagram.prototype.updateOptions=function(t){var e=this;e.options=jQuery.extend(!0,{},e.options,t),e.updateGlobals()},MutationDiagram.prototype.rescaleYAxis=function(t){var e=this;e.updateGlobals(),e.svg.select(".mut-dia-y-axis").remove(),e.drawYAxis(e.svg,e.yScale,e.yMax,e.options,e.bounds),t||e.updatePlot()},MutationDiagram.prototype.updateGlobals=function(t){var e=this;t=t||e.options;var n=e.data.pileups;t.yAxisAutoAdjust&&(n=e.pileups);var i=e.maxCount=e.calcMaxCount(n),a=e.xMax=e.calcXMax(t,e.data),o=e.yMax=e.calcYMax(t,i);e.bounds=this.calcBounds(t),e.xScale=this.xScaleFn(e.bounds,a),e.yScale=this.yScaleFn(e.bounds,o)},MutationDiagram.prototype.updateSequenceData=function(t){var e=this;e.data.sequence=t},MutationDiagram.prototype.initDiagram=function(){var t=this,e=$(t.options.el)[0],n=d3.select(e),i=t.bounds=t.calcBounds(t.options);t.mutationPileupMap=PileupUtil.mapToMutations(t.data.pileups);var a=t.createSvg(n,t.options.elWidth,t.options.elHeight);t.svg=a,t.drawDiagram(a,i,t.options,t.data),t.addDefaultListeners()},MutationDiagram.prototype.calcBounds=function(t){var e={};return e.width=t.elWidth-(t.marginLeft+t.marginRight),e.height=t.elHeight-(t.marginBottom+t.marginTop),e.x=t.marginLeft,e.y=t.elHeight-t.marginBottom,e},MutationDiagram.prototype.drawDiagram=function(t,e,n,i){var a=this,o=(parseInt(i.sequence.length),a.maxCount=a.calcMaxCount(i.pileups)),r=a.xMax=a.calcXMax(n,i),l=a.yMax=a.calcYMax(n,o),s=i.sequence.regions,u=i.pileups,c=a.generateSequenceTooltip(i),d=a.xScale=a.xScaleFn(e,r),p=a.yScale=a.yScaleFn(e,l);a.drawXAxis(t,d,r,n,e),0!=n.labelX,a.drawYAxis(t,p,l,n,e),0!=n.labelY&&(a.yAxisLabel=a.drawYAxisLabel(t,n,e)),0!=n.topLabel&&(a.topLabel=a.drawTopLabel(t,n,e));t.append("rect").attr("fill","#FFFFFF").attr("opacity",0).attr("x",e.x).attr("y",e.y-e.height).attr("width",e.width).attr("height",e.height).attr("class","mut-dia-background");a.drawPlot(t,u,n,e,d,p);var m=a.drawSequence(t,n,e);m.attr("title",c);for(var h=0,f=s.length;f>h;h++)a.drawRegion(t,s[h],n,e,d)},MutationDiagram.prototype.xScaleFn=function(t,e){return d3.scale.linear().domain([0,e]).range([t.x,t.x+t.width])},MutationDiagram.prototype.yScaleFn=function(t,e){return d3.scale.linear().domain([0,e]).range([t.y,t.y-t.height])},MutationDiagram.prototype.calcXMax=function(t,e){var n=parseInt(e.sequence.length);return Math.min(t.maxLengthX,Math.max(n,t.minLengthX))},MutationDiagram.prototype.calcYMax=function(t,e){return Math.min(t.maxLengthY,Math.max(e,t.minLengthY))},MutationDiagram.prototype.generateSequenceTooltip=function(t){var e="",n=parseInt(t.sequence.length);return t.sequence.metadata.identifier&&(e+=t.sequence.metadata.identifier,t.sequence.metadata.description&&(e+=", "+t.sequence.metadata.description)),e+=" ("+n+"aa)"},MutationDiagram.prototype.drawPlot=function(t,e,n,i,a,o){var r=this,l=r.gLabel;null===l&&(l=t.append("g").attr("class","mut-dia-lollipop-labels"),r.gLabel=l);var s=r.gLine;null===s&&(s=t.append("g").attr("class","mut-dia-lollipop-lines"),r.gLine=s);var u=r.gData;null===u&&(u=t.append("g").attr("class","mut-dia-lollipop-points"),r.gData=u);for(var c=0;co)break}return i},MutationDiagram.prototype.getTickValues=function(t,e){for(var n=[],i=0;t>i;)n.push(i),i+=e/2;return n.push(t),n},MutationDiagram.prototype.drawXAxis=function(t,e,n,i,a){var o=this,r=o.calcTickInterval(i.xAxisTickIntervals,n,i.xAxisTicks),l=o.getTickValues(n,r),s=function(t){return t==n?t+" aa":t%r!=0?"":n-t>r/3?t:""},u=i.xAxisTickSize,c=d3.svg.axis().scale(e).orient("bottom").tickValues(l).tickFormat(s).tickSize(u,u/2,0),d=a.y+i.regionHeight+i.xAxisPadding,p=t.append("g").attr("class","mut-dia-x-axis").attr("transform","translate(0,"+d+")").call(c);return o.formatAxis(".mut-dia-x-axis",i.xAxisStroke,i.xAxisFont,i.xAxisFontSize,i.xAxisFontColor),p},MutationDiagram.prototype.drawYAxis=function(t,e,n,i,a){var o=this,r=o.calcTickInterval(i.yAxisTickIntervals,n,i.yAxisTicks),l=o.getTickValues(n,2*r),s=function(t){var e="";return t===n?(e=t,o.maxCount>n&&(e=">"+t)):0===t&&(e=t),e},u=i.yAxisTickSize,c=d3.svg.axis().scale(e).orient("left").tickValues(l).tickFormat(s).tickSize(u,u/2,0),d=a.x-i.yAxisPadding,p=t.append("g").attr("class","mut-dia-y-axis").attr("transform","translate("+d+",0)").call(c);return o.formatAxis(".mut-dia-y-axis",i.yAxisStroke,i.yAxisFont,i.yAxisFontSize,i.yAxisFontColor),p},MutationDiagram.prototype.drawTopLabel=function(t,e,n){var i=e.labelTopMargin,a=e.marginTop/2,o=t.append("text").attr("fill",e.labelTopFontColor).attr("text-anchor","start").attr("x",i).attr("y",a).attr("class","mut-dia-top-label").style("font-family",e.labelTopFont).style("font-size",e.labelTopFontSize).style("font-weight",e.labelTopFontWeight).text(e.labelTop);return o},MutationDiagram.prototype.drawYAxisLabel=function(t,e,n){var i=n.x-e.yAxisPadding-e.yAxisTickSize-e.yAxisLabelPadding,a=n.y-n.height/2,o=t.append("text").attr("fill",e.labelYFontColor).attr("text-anchor","middle").attr("x",i).attr("y",a).attr("class","mut-dia-y-axis-label").attr("transform","rotate(270, "+i+","+a+")").style("font-family",e.labelYFont).style("font-size",e.labelYFontSize).style("font-weight",e.labelYFontWeight).text(e.labelY);return o},MutationDiagram.prototype.formatAxis=function(t,e,n,i,a){var o=d3.selectAll(t+" line");o.style("fill","none").style("stroke",e).style("shape-rendering","crispEdges"),o=d3.selectAll(t+" path"),o.style("fill","none").style("stroke",e).style("shape-rendering","crispEdges"),o=d3.selectAll(t+" text"),o.attr("fill",a).style("font-family",n).style("font-size",i)},MutationDiagram.prototype.drawLollipop=function(t,e,n,i,a,o,r){var l=this,s=i.lollipopShapeRegular,u=n.count,c=n.location,d=o(c),p=r(u);u>i.maxLengthY&&(s=i.lollipopShapeSpecial,p=r(i.maxLengthY));var m=l.getLollipopFillColor(i,n);l.updateColorMap(n,m);var h=t.append("path").attr("d",d3.svg.symbol().size(i.lollipopSize).type(s)).attr("transform","translate("+d+","+p+")").attr("fill",m).attr("stroke",i.lollipopBorderColor).attr("stroke-width",i.lollipopBorderWidth).attr("id",n.pileupId).attr("class","mut-dia-data-point").attr("opacity",0);l.fadeIn(h),h.datum(n);var f=i.lollipopTipFn;f(h,n,i.showStats);var g=e.append("line").attr("x1",d).attr("y1",p).attr("x2",d).attr("y2",l.calcSequenceBounds(a,i).y).attr("stroke",i.lollipopStrokeColor).attr("stroke-width",i.lollipopStrokeWidth).attr("class","mut-dia-data-line").attr("opacity",0);return l.fadeIn(g),{dataPoint:h,line:g}},MutationDiagram.prototype.updateColorMap=function(t,e){for(var n=this,i=0;it.options.maxLengthY&&(n=t.options.lollipopShapeSpecial),n};return e},MutationDiagram.prototype.getLollipopFillColor=function(t,e){var n,i=t.lollipopFillColor;if(_.isFunction(i))n=i(e);else if(_.isString(i))n=i;else{var a=PileupUtil.groupMutationsByMainType(e);n=0===a.length?i["default"]:i[a[0].type]}return n},MutationDiagram.prototype.drawLollipopLabels=function(t,e,n,i,a){var o=this,r=function(t,e){var i=e;if("auto"==i.toLowerCase()){var a=t.attr("x")-t.node().getComputedTextLength()/2;i=a1){for(var u=e[0].count,c=0;cl&&c>s&&(l=0)}for(var d=0;l>d&&d1&&e[d].counti&&(t=t.substring(0,3)+"..",r.text(t),r.node().getComputedTextLength()>i&&(r.remove(),r=null)),r},MutationDiagram.prototype.drawSequence=function(t,e,n){var i=this.calcSequenceBounds(n,e);return t.append("rect").attr("fill",e.seqFillColor).attr("x",i.x).attr("y",i.y).attr("width",i.width).attr("height",i.height).attr("class","mut-dia-sequence")},MutationDiagram.prototype.calcMaxCount=function(t){var e=-1;return t.length>0&&(e=t[0].count),e},MutationDiagram.prototype.calcSequenceBounds=function(t,e){var n=t.x,i=t.y+Math.abs(e.regionHeight-e.seqHeight)/2+e.seqPadding,a=t.width,o=e.seqHeight;return{x:n,y:i,width:a,height:o}},MutationDiagram.prototype.updatePlot=function(t){var e=this,n=e.pileups;return t&&(e.pileups=n=t,e.mutationPileupMap=PileupUtil.mapToMutations(n)),e.cleanPlotArea(),e.mutationColorMap={},e.options.yAxisAutoAdjust&&e.rescaleYAxis(!0),e.drawPlot(e.svg,n,e.options,e.bounds,e.xScale,e.yScale),_.each(_.keys(e.listeners),function(t){var n=e.svg.selectAll(t);_.each(_.keys(e.listeners[t]),function(i){n.on(i,e.listeners[t][i])})}),e.highlighted={},e.dispatcher.trigger(MutationDetailsEvents.DIAGRAM_PLOT_UPDATED),e.isFiltered()},MutationDiagram.prototype.cleanPlotArea=function(){var t=this,e=t.gLabel.selectAll("text"),n=t.gLine.selectAll("line"),i=t.gData.selectAll(".mut-dia-data-point");t.fadeOut(e,function(t){$(t).remove()}),t.fadeOut(n,function(t){$(t).remove()}),t.fadeOut(i,function(t){$(t).remove()})},MutationDiagram.prototype.resetPlot=function(){var t=this;t.updatePlot(t.data.pileups),t.dispatcher.trigger(MutationDetailsEvents.DIAGRAM_PLOT_RESET)},MutationDiagram.prototype.updateTopLabel=function(t){var e=this;(void 0==t||null==t)&&(t=""),e.topLabel.text(t)},MutationDiagram.prototype.addListener=function(t,e,n){var i=this;i.svg.selectAll(t).on(e,n),null==i.listeners[t]&&(i.listeners[t]={}),i.listeners[t][e]=n},MutationDiagram.prototype.removeListener=function(t,e){var n=this;n.svg.selectAll(t).on(e,null),n.listeners[t]&&n.listeners[t][e]&&delete n.listeners[t][e]},MutationDiagram.prototype.addDefaultListeners=function(){var t=this;t.addListener(".mut-dia-background","click",function(e,n){var i=!t.isHighlighted()||t.multiSelect;i||(t.clearHighlights(),t.dispatcher.trigger(MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED))}),t.addListener(".mut-dia-data-point","click",function(e,n){t.isHighlighted(this)?(t.removeHighlight(this),t.multiSelect||t.clearHighlights(),t.dispatcher.trigger(MutationDetailsEvents.LOLLIPOP_DESELECTED,e,n)):(t.multiSelect||t.clearHighlights(),t.highlight(this),t.dispatcher.trigger(MutationDetailsEvents.LOLLIPOP_SELECTED,e,n))}),t.addListener(".mut-dia-data-point","mouseout",function(e,n){t.dispatcher.trigger(MutationDetailsEvents.LOLLIPOP_MOUSEOUT,e,n)}),t.addListener(".mut-dia-data-point","mouseover",function(e,n){t.dispatcher.trigger(MutationDetailsEvents.LOLLIPOP_MOUSEOVER,e,n)});var e=function(e,n){t.multiSelect&&d3.event.preventDefault()};t.addListener(".mut-dia-data-point","mousedown",e),t.addListener(".mut-dia-background","mousedown",e),$(window).on("keydown",function(e){e.keyCode==t.options.multiSelectKeycode&&(t.multiSelect=!0)}),$(window).on("keyup",function(e){e.keyCode==t.options.multiSelectKeycode&&(t.multiSelect=!1)})},MutationDiagram.prototype.isHighlighted=function(t){var e=this,n=!1;if(void 0==t)n=!_.isEmpty(e.highlighted);else{var i=d3.select(t),a=i.datum().location;void 0!=e.highlighted[a]&&(n=!0)}return n},MutationDiagram.prototype.clearHighlights=function(){var t=this,e=t.gData.selectAll(".mut-dia-data-point");e.transition().ease("elastic").duration(t.options.animationDuration).attr("d",d3.svg.symbol().size(t.options.lollipopSize).type(t.getLollipopShapeFn())),t.highlighted={}},MutationDiagram.prototype.highlightMutation=function(t){var e=this,n=e.mutationPileupMap[t],i=e.svg.select("#"+n);i.length>0&&e.highlight(i[0][0])},MutationDiagram.prototype.highlight=function(t){var e=this,n=d3.select(t);n.transition().ease("elastic").duration(e.options.animationDuration).attr("d",d3.svg.symbol().size(e.options.lollipopHighlightSize).type(e.getLollipopShapeFn()));var i=n.datum().location;e.highlighted[i]=n},MutationDiagram.prototype.removeHighlight=function(t){var e=this,n=d3.select(t);n.transition().ease("elastic").duration(e.options.animationDuration).attr("d",d3.svg.symbol().size(e.options.lollipopSize).type(e.getLollipopShapeFn()));var i=n.datum().location;delete e.highlighted[i]},MutationDiagram.prototype.fadeIn=function(t,e){var n=this;t.transition().style("opacity",1).duration(n.options.fadeDuration).each("end",function(){_.isFunction(e)&&e(this)})},MutationDiagram.prototype.fadeOut=function(t,e){var n=this;t.transition().style("opacity",0).duration(n.options.fadeDuration).each("end",function(){_.isFunction(e)&&e(this)})},MutationDiagram.prototype.getSelectedElements=function(){var t=this;return _.values(t.highlighted)},MutationDiagram.prototype.isFiltered=function(){var t=this,e=!1;return PileupUtil.countMutations(t.pileups)
- + Loading 3d visualization
@@ -89,13 +89,15 @@ checked='checked'> Display bound molecules - + Help (non-protein display) - - + Help (protein coloring) @@ -138,7 +142,8 @@ Display side chain - - + Help (side chain display) @@ -164,7 +170,8 @@ checked='checked'> mutation type - + Help (mutation type coloring) @@ -179,7 +186,8 @@ - - + Help (mutation type coloring) @@ -240,10 +249,6 @@

3D visualizer basic interaction

(Nonsense, Nonstop, FS del, FS ins)
  • Inframe Mutations (IF del, IF ins)
  • -
  • - Residues colored with purple indicate residues - that are affected by different mutation types at the same proportion. -
  • None: Disables coloring of the mutated residues except for manually selected (highlighted) residues.
    @@ -285,6 +290,22 @@

    3D visualizer basic interaction

    This option has no effect if the current structure does not contain any co-crystalized bound molecules. + + + @@ -510,8 +533,12 @@

    {{gene}} mutations across all cancer studies


    - + + @@ -612,7 +635,7 @@

    Color Codes

    {{identifier}} {{type}}, {{description}} ({{start}} - {{end}})
    - PFAM + PFAM {{mutationAlignerInfo}}
    @@ -715,7 +738,7 @@

    Color Codes

    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; +__p += '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; } return __p