From 26a09d011a3aa42daf5b4a087a046f8b075101cf Mon Sep 17 00:00:00 2001 From: pshannon-bioc Date: Tue, 15 Dec 2015 13:14:48 -0800 Subject: [PATCH 1/5] removed some obsolete functions, added many comments --- Oncoscape/inst/scripts/blankTab/Module.js | 2 + .../inst/scripts/markersAndSamples/Module.js | 173 +++---- .../inst/scripts/markersAndSamples/index.html | 474 ++++++++++++++---- .../inst/scripts/markersAndSamples/index.pre | 3 + .../log.2015-11-13.18:16:49.RData | Bin 2262 -> 0 bytes 5 files changed, 455 insertions(+), 197 deletions(-) delete mode 100644 Oncoscape/inst/scripts/markersAndSamples/log.2015-11-13.18:16:49.RData diff --git a/Oncoscape/inst/scripts/blankTab/Module.js b/Oncoscape/inst/scripts/blankTab/Module.js index af75ca6da..a1ed8f10e 100644 --- a/Oncoscape/inst/scripts/blankTab/Module.js +++ b/Oncoscape/inst/scripts/blankTab/Module.js @@ -75,6 +75,7 @@ function sendSelections(event) //-------------------------------------------------------------------------------------------- function handleSelections(msg) { + hub.enableTab(thisModulesOutermostDiv); hub.raiseTab(thisModulesOutermostDiv); var msgAsString = JSON.stringify(msg.payload); @@ -217,6 +218,7 @@ function initializeModule() hub.addMessageHandler("sendSelectionTo_blankTab", handleSelections); hub.addMessageHandler("blankTabAssessUserIdForTesting", assessUserIdForTesting) hub.addSocketConnectedFunction(runAutomatedTestsIfAppropriate); + hub.enableTab(thisModulesOutermostDiv); } // initializeModule //---------------------------------------------------------------------------------------------------- diff --git a/Oncoscape/inst/scripts/markersAndSamples/Module.js b/Oncoscape/inst/scripts/markersAndSamples/Module.js index 011e0f866..1421e47cb 100644 --- a/Oncoscape/inst/scripts/markersAndSamples/Module.js +++ b/Oncoscape/inst/scripts/markersAndSamples/Module.js @@ -1,8 +1,6 @@ //---------------------------------------------------------------------------------------------------- -// move these all back inside module scope when debugging is done - +// declare the cytoscape object in global scope, permitting easy manipulation in the javascript console. var cwMarkers; -var markersTester; //---------------------------------------------------------------------------------------------------- var markersAndTissuesModule = (function () { @@ -76,10 +74,6 @@ function initializeUI () markersShowEdgesFromButton.click(showEdgesFromSelectedNodes); hub.disableButton(markersShowEdgesFromButton); - //$("#markersFitViewButton").click(function(){cwMarkers.fit();}); - //$("#markersHideEdgesButton").click(hideAllEdges); - //$("#markersShowEdgesFromSelectedButton").click(showEdgesFromSelectedNodes); - tumorCategorizationsMenu = $("#cyMarkersTumorCategorizationsMenu"); tumorCategorizationsMenu.empty(); tumorCategorizationsMenu.append(""); @@ -207,17 +201,22 @@ function sendSelections(event) } // sendSelections //-------------------------------------------------------------------------------------------- -function configureLayoutsMenu(layoutMenu){ - +// we currently support a limited amount cyjs layout save and restore. +// among the limitations are: +// a) they are saved on the user's computer +// b) they can only be retrieved if the same computer, the same browser, and the same url +// is used +function configureLayoutsMenu(layoutMenu) +{ console.log("--- configureLayoutsMenu"); layoutMenu.append(""); layoutMenu.append(""); var defaultLayout = JSON.stringify(cwMarkers.nodes().map(function(n){ - var result = {id:n.id(), position:n.position()}; - return (result); - }) // map - ); // stringify + var result = {id:n.id(), position:n.position()}; + return (result); + }) // map + ); // stringify localStorage.markersDefault = defaultLayout; @@ -260,20 +259,6 @@ function performLayout(event){ } // performLayout //-------------------------------------------------------------------------------------------- -function sendSelection() -{ - destinationModule = sendSelectionsMenu.val(); - var nodeNames = selectedNodeNames(cwMarkers); - if(nodeNames.length === 0){ - console.log("no nodes selected!"); - return; - } - metadata = {}; - sendSelectionToModule(destinationModule, nodeNames, metadata); - sendSelectionsMenu.val("Send Selection..."); - -} // sendSelectionsMenuChanged -//-------------------------------------------------------------------------------------------- function configureCytoscape () { cwMarkers = $("#cyMarkersDiv"); @@ -330,12 +315,13 @@ function configureCytoscape () } // configureCytoscape //---------------------------------------------------------------------------------------------------- -function handleWindowResize () +function handleWindowResize() { cyDiv.width(0.95 * $(window).width()); cyDiv.height(0.8 * $(window).height()); + // todo: should preserve preceeding view. cwMarkers.resize(); - cwMarkers.fit(50); + cwMarkers.fit(50); } // handleWindowResize //---------------------------------------------------------------------------------------------------- @@ -362,12 +348,17 @@ function debounce(func, wait, immediate) // expand node size and display node labels when: // 1) the user's coordinate space, due to zooming, has shrunk to < 600 pixels // 2) the zoom factor is so large relative to the initial zoom (a global variable, set on startup) -// +// +// the current implemetation is decidely imperfect. the operations accomplished here take too +// long, creating a sometimes quite unsatisfying user experience. +// this has been mitigated somewhat by +// - deboucncing (at some interval) +// - expanding nodes, adjusting font, node border and edge width only when well zoomed in +// AND a modest number of nodes are onscreen +// - trying to avoid layout when possible in the base network. +// function smartZoom(event) { - //console.log("smartZoom"); - var queuedEvents = $("#cyMarkersDiv").queue(); - var zoomRatio = cwMarkers.zoom()/initialZoom; console.log("zoomRatio: " + zoomRatio); @@ -380,8 +371,6 @@ function smartZoom(event) var visibleOnScreen = function(node){ if(node.data("landmark")) return(false); - //var x = node.position().x; - //var y = node.position().y; var bbox = node.boundingBox(); var visibleX = (bbox.x1 >= visibleCoords.x1 && bbox.x1 <= visibleCoords.x2) | (bbox.x2 >= visibleCoords.x1 && bbox.x2 <= visibleCoords.x2); @@ -390,27 +379,17 @@ function smartZoom(event) var visibleY = (bbox.y1 >= visibleCoords.y1 && bbox.y1 <= visibleCoords.y2) | (bbox.y2 >= visibleCoords.y1 && bbox.y2 <= visibleCoords.y2); return(visibleY); - //return(x >= visibleCoords.x1 && x <= visibleCoords.x2 && - // y >= visibleCoords.y1 && y <= visibleCoords.y2); }; - //console.log("starting calculation of visibleNodes"); var visibleNodes = cwMarkers.nodes().fnFilter(function(node){return(visibleOnScreen(node));}); console.log("visibleNode count: " + visibleNodes.length); if(visibleNodes.length > 400){ defaultStyle(); - //console.log("returning, visibleNode count: " + visibleNodes.length); return; } - //console.log("need to smartZoom, setting hanlder off to discard queued events"); - //cwMarkers.off('zoom', smartZoom); - - //console.log(event); var newZoom = 1.0 + cwMarkers.zoom() - oldZoom; oldZoom = cwMarkers.zoom(); // keep this for next time - //console.log("complete"); - // TODO: these two ratios might be reduced to just one var windowRatio = cwMarkers.width()/cwMarkers.extent().h; @@ -421,8 +400,6 @@ function smartZoom(event) var fontSizeString = fontSize + "px"; var borderWidthString = cwMarkers.extent().h/600 + "px"; - //console.log("--- new fontsize: " + fontSizeString); - //console.log("--- new borderWidth: " + borderWidthString); cwMarkers.edges().style({"width": borderWidthString}); var newWidth, newHeight, id; @@ -438,23 +415,21 @@ function smartZoom(event) }); }); - //console.log("visibleNode mapping complete, adding smartZoom handler back"); - //cwMarkers.on('zoom', smartZoom); - - } // smartZoom //---------------------------------------------------------------------------------------------------- +// undo any changes brought about during smartZoom. +// TODO: it seems a better approach would be to remove the zoomed attribute, and apply the style rules +// everywhere with which the network was initialized. function defaultStyle() { var zoomedNodes = cwMarkers.nodes("[zoomed]"); - // console.log("restoring default style, zoomed node count: " + zoomedNodes.length); cwMarkers.edges().style({"width": "1px"}); - zoomedNodes.map(function(node){node.style({width: node.data('trueWidth'), - height: node.data('trueHeight'), + zoomedNodes.map(function(node){node.style({width: node.data("trueWidth"), + height: node.data("trueHeight"), zoomed: false, - 'border-width': "1px", - 'font-size': "3px"});}); + "border-width": "1px", + "font-size": "3px"});}); } // defaultStyle //---------------------------------------------------------------------------------------------------- @@ -549,25 +524,52 @@ function requestTumorCategorization() } // requestTumorCategorization //---------------------------------------------------------------------------------------------------- +// msg.payload has 3 fields: colnames, rownames, tbl +// colnames: ["cluster", "color"] +// rownames: possibly large number of tumors (samples) with category (cluster) & color assigned +// tbl: a matrix, rownames.length x colnames.lenght, of cluster and color assignments +// representing this data structure +// cluster color +// TCGA.08.0525 Classical chocolate +// ... +// +// strategy: +// get unique cluster/color pairs (far fewer of these, typically, than sample ids (tbl rows). +// each sample named in the tbl, and also found in the network, will get a "category" (aka "cluster") +// attribute assigned to it near the end of this function. +// first, however, cyjs/css style rules are handcrafted, one for unique cluster value, and one +// for each cluster value if the node is selected. + function applyTumorCategorization(msg) { console.log("=== applyTumorCategorization"); + var tumorsInGraph = cwMarkers.nodes("[nodeType='patient']"); var tumorsInTable = msg.payload.rownames; var tbl = msg.payload.tbl; var categoryRules = {}; - tbl.forEach(function(row){categoryRules[row[0]] = row[1];}); + // this forEach loop inelegantly reduces many rows to a unique set + // by overwriting, e.g., categoryRules["G-CIMP"] = "purple" each of + // the time it is seen. this inefficiency could be eliminated by + // sending across just the unique rules from R as a payload field + // (and also removing the color column from tbl). + + tbl.forEach(function(row){categoryRules[row[0]] = row[1];}); - /* jshint ignore:start */ - //debugger; - /* jshint ignore:end */ categoryRuleNames = Object.keys(categoryRules); + // e.g. ["G-CIMP", "Classical", "null", "Proneural", "Neural", "Mesenchymal"] categoryRuleNames.filter(function(name){return name !== "null";}); categoryRuleNames.filter(function(name){return name !== null;}); var newRules = []; + // translate the categoryRules into cyjs/css style rules, which + // look like this: + // {"selector":"node[category='Classical']","style":{"background-color":"chocolate"}} + // {"selector":"node[category='Classical']:selected", + // "style":{"border-color":"red","background-color":"chocolate","border-width":"10px"}}" + categoryRuleNames.forEach(function(name){ var selector = "node[category='" + name + "']"; color=categoryRules[name]; @@ -591,6 +593,10 @@ function applyTumorCategorization(msg) hub.logEventOnServer(thisModulesName, "markersApplyTumorCategorization", "data received", ""); + // iterate across the tumor ('patient') nodes, add a category attribute, assign + // a cluster value from the tbl, which will select one of the style rules just + // created above. + console.log("starting tumorsInGraph.forEach"); cwMarkers.batch(function() { tumorsInGraph.forEach(function(node, index){ @@ -598,7 +604,6 @@ function applyTumorCategorization(msg) var indexInTable = tumorsInTable.indexOf(nodeID); if(indexInTable >= 0){ var cluster = tbl[indexInTable][0]; - var color = tbl[indexInTable][1]; node.data({category: cluster}); } else{ @@ -609,6 +614,9 @@ function applyTumorCategorization(msg) console.log("ending tumorsInGraph.forEach"); + // get a copy of the current style, remove any old node-category style rules, add the new ones + // set this new style + var oldStyle = cwMarkers.style().json(); // remove any pre-existing node category rules var oldStyleClean = oldStyle.filter(function(e){return(e.selector.indexOf("node[category"));}); @@ -746,40 +754,6 @@ function handleIncomingIdentifiers(msg) hub.raiseTab(thisModulesOutermostDiv); } // handleIncomingIdentifiers -//---------------------------------------------------------------------------------------------------- - // run all that should happen when this module receives an incoming selection of patientIDs -function demoMarkersIncomingSelectionOfIDs() -{ - - names = ["TCGA.06.0210", "TCGA.02.0106", "TCGA.02.0111", - "TCGA.06.0194", "TCGA.06.0164", "TCGA.06.0409", "TCGA.02.0004", - "TCGA.02.0051", "TCGA.08.0390", "TCGA.02.0025", "TCGA.08.0392", - "TCGA.02.0079", "TCGA.12.0620", "TCGA.08.0373", "TCGA.06.0645", - "TCGA.06.0192", "TCGA.12.0776", "TCGA.12.0778", "TCGA.06.0750", - "TCGA.06.0878", "TCGA.14.0789", "TCGA.06.0881", "BCL11A", - "BRCA1", "MDM2", "PIK3R1", "ABCA1", "CDK6", "CNTRL", "FH", - "IFNA1", "LMO2", "PRKCA", "RELA", "STK11", "ZEB1", "CCNB1IP1", - "CREB3L1", "GDF2", "OR4K2", "PRKCH", "WAS"]; - - subset = []; - for(var i=0; i < 10; i++) - subset.push(names[getRandomInt(0, names.length -1)]); - - selectNodes(subset); - -} // demoIncomingSelectionOfPatientIDs -//---------------------------------------------------------------------------------------------------- -function allNodeIDs() -{ - ids = []; - allNodes = cwMarkers.nodes(); - - for(i=0; i < allNodes.length; i++) - ids.push(allNodes[i].data("id")); - - return(ids); - -} // allNodeIDs //---------------------------------------------------------------------------------------------------- function showEdges() { @@ -1027,7 +1001,7 @@ function selectNodes(nodeNames) } // selectNodes //---------------------------------------------------------------------------------------------------- - // todo: build up the filter string first, then send it all at once +// todo: build up the filter string first, then send it all at once function selectNodesByID(nodeIDs) { if(typeof(nodeIDs) == "string") // trap scalar, but expect and support arrays @@ -1082,8 +1056,11 @@ function displayMarkersNetwork(msg) cwMarkers.filter("edge[edgeType='chromosome']").style({"curve-style": "bezier"}); cwMarkers.filter("edge[edgeType='chromosome']").show(); cwMarkers.nodes().unselect(); - // map current node degree into a node attribute of that name - cwMarkers.nodes().map(function(node){node.data({degree: node.degree(), trueWidth: node.width(), trueHeight: node.height()});}); + // map current node degree into a node attribute of that name, + // save the initial width and height to restore values after zooming. + cwMarkers.nodes().map(function(node){node.data({degree: node.degree(), + trueWidth: node.width(), + trueHeight: node.height()});}); var edgeTypes = hub.uniqueElementsOfArray(cwMarkers.edges().map(function(edge){ return(edge.data("edgeType"));} diff --git a/Oncoscape/inst/scripts/markersAndSamples/index.html b/Oncoscape/inst/scripts/markersAndSamples/index.html index a1fb21305..d9d7546eb 100644 --- a/Oncoscape/inst/scripts/markersAndSamples/index.html +++ b/Oncoscape/inst/scripts/markersAndSamples/index.html @@ -1237,10 +1237,8 @@ hub.registerModule("Datasets", dataSummaryModule); //---------------------------------------------------------------------------------------------------- -// move these all back inside module scope when debugging is done - +// declare the cytoscape object in global scope, permitting easy manipulation in the javascript console. var cwMarkers; -var markersTester; //---------------------------------------------------------------------------------------------------- var markersAndTissuesModule = (function () { @@ -1314,10 +1312,6 @@ markersShowEdgesFromButton.click(showEdgesFromSelectedNodes); hub.disableButton(markersShowEdgesFromButton); - //$("#markersFitViewButton").click(function(){cwMarkers.fit();}); - //$("#markersHideEdgesButton").click(hideAllEdges); - //$("#markersShowEdgesFromSelectedButton").click(showEdgesFromSelectedNodes); - tumorCategorizationsMenu = $("#cyMarkersTumorCategorizationsMenu"); tumorCategorizationsMenu.empty(); tumorCategorizationsMenu.append(""); @@ -1445,17 +1439,22 @@ } // sendSelections //-------------------------------------------------------------------------------------------- -function configureLayoutsMenu(layoutMenu){ - +// we currently support a limited amount cyjs layout save and restore. +// among the limitations are: +// a) they are saved on the user's computer +// b) they can only be retrieved if the same computer, the same browser, and the same url +// is used +function configureLayoutsMenu(layoutMenu) +{ console.log("--- configureLayoutsMenu"); layoutMenu.append(""); layoutMenu.append(""); var defaultLayout = JSON.stringify(cwMarkers.nodes().map(function(n){ - var result = {id:n.id(), position:n.position()}; - return (result); - }) // map - ); // stringify + var result = {id:n.id(), position:n.position()}; + return (result); + }) // map + ); // stringify localStorage.markersDefault = defaultLayout; @@ -1498,20 +1497,6 @@ } // performLayout //-------------------------------------------------------------------------------------------- -function sendSelection() -{ - destinationModule = sendSelectionsMenu.val(); - var nodeNames = selectedNodeNames(cwMarkers); - if(nodeNames.length === 0){ - console.log("no nodes selected!"); - return; - } - metadata = {}; - sendSelectionToModule(destinationModule, nodeNames, metadata); - sendSelectionsMenu.val("Send Selection..."); - -} // sendSelectionsMenuChanged -//-------------------------------------------------------------------------------------------- function configureCytoscape () { cwMarkers = $("#cyMarkersDiv"); @@ -1568,12 +1553,13 @@ } // configureCytoscape //---------------------------------------------------------------------------------------------------- -function handleWindowResize () +function handleWindowResize() { cyDiv.width(0.95 * $(window).width()); cyDiv.height(0.8 * $(window).height()); + // todo: should preserve preceeding view. cwMarkers.resize(); - cwMarkers.fit(50); + cwMarkers.fit(50); } // handleWindowResize //---------------------------------------------------------------------------------------------------- @@ -1600,12 +1586,17 @@ // expand node size and display node labels when: // 1) the user's coordinate space, due to zooming, has shrunk to < 600 pixels // 2) the zoom factor is so large relative to the initial zoom (a global variable, set on startup) -// +// +// the current implemetation is decidely imperfect. the operations accomplished here take too +// long, creating a sometimes quite unsatisfying user experience. +// this has been mitigated somewhat by +// - deboucncing (at some interval) +// - expanding nodes, adjusting font, node border and edge width only when well zoomed in +// AND a modest number of nodes are onscreen +// - trying to avoid layout when possible in the base network. +// function smartZoom(event) { - //console.log("smartZoom"); - var queuedEvents = $("#cyMarkersDiv").queue(); - var zoomRatio = cwMarkers.zoom()/initialZoom; console.log("zoomRatio: " + zoomRatio); @@ -1618,8 +1609,6 @@ var visibleOnScreen = function(node){ if(node.data("landmark")) return(false); - //var x = node.position().x; - //var y = node.position().y; var bbox = node.boundingBox(); var visibleX = (bbox.x1 >= visibleCoords.x1 && bbox.x1 <= visibleCoords.x2) | (bbox.x2 >= visibleCoords.x1 && bbox.x2 <= visibleCoords.x2); @@ -1628,27 +1617,17 @@ var visibleY = (bbox.y1 >= visibleCoords.y1 && bbox.y1 <= visibleCoords.y2) | (bbox.y2 >= visibleCoords.y1 && bbox.y2 <= visibleCoords.y2); return(visibleY); - //return(x >= visibleCoords.x1 && x <= visibleCoords.x2 && - // y >= visibleCoords.y1 && y <= visibleCoords.y2); }; - //console.log("starting calculation of visibleNodes"); var visibleNodes = cwMarkers.nodes().fnFilter(function(node){return(visibleOnScreen(node));}); console.log("visibleNode count: " + visibleNodes.length); if(visibleNodes.length > 400){ defaultStyle(); - //console.log("returning, visibleNode count: " + visibleNodes.length); return; } - //console.log("need to smartZoom, setting hanlder off to discard queued events"); - //cwMarkers.off(zoom', smartZoom); - - //console.log(event); var newZoom = 1.0 + cwMarkers.zoom() - oldZoom; oldZoom = cwMarkers.zoom(); // keep this for next time - //console.log("complete"); - // TODO: these two ratios might be reduced to just one var windowRatio = cwMarkers.width()/cwMarkers.extent().h; @@ -1659,8 +1638,6 @@ var fontSizeString = fontSize + "px"; var borderWidthString = cwMarkers.extent().h/600 + "px"; - //console.log("--- new fontsize: " + fontSizeString); - //console.log("--- new borderWidth: " + borderWidthString); cwMarkers.edges().style({"width": borderWidthString}); var newWidth, newHeight, id; @@ -1676,23 +1653,21 @@ }); }); - //console.log("visibleNode mapping complete, adding smartZoom handler back"); - //cwMarkers.on('zoom', smartZoom); - - } // smartZoom //---------------------------------------------------------------------------------------------------- +// undo any changes brought about during smartZoom. +// TODO: it seems a better approach would be to remove the zoomed attribute, and apply the style rules +// everywhere with which the network was initialized. function defaultStyle() { var zoomedNodes = cwMarkers.nodes("[zoomed]"); - // console.log("restoring default style, zoomed node count: " + zoomedNodes.length); cwMarkers.edges().style({"width": "1px"}); - zoomedNodes.map(function(node){node.style({width: node.data('trueWidth'), - height: node.data('trueHeight'), + zoomedNodes.map(function(node){node.style({width: node.data("trueWidth"), + height: node.data("trueHeight"), zoomed: false, - 'border-width': "1px", - 'font-size': "3px"});}); + "border-width": "1px", + "font-size": "3px"});}); } // defaultStyle //---------------------------------------------------------------------------------------------------- @@ -1704,7 +1679,7 @@ // function subSelectNodes() { - var selectedPatientNodes = cwMarkers.nodes("node[nodeType='patient']:selected"); + var selectedPatientNodes = cwMarkers.nodes("node[nodeType=patient']:selected"); var categories = jQuery.unique(selectedPatientNodes.map(function(e){return e.data("category");})); var colors = jQuery.unique(selectedPatientNodes.map(function(node){return (node.style("background-color"));})); @@ -1787,25 +1762,52 @@ } // requestTumorCategorization //---------------------------------------------------------------------------------------------------- +// msg.payload has 3 fields: colnames, rownames, tbl +// colnames: ["cluster", "color"] +// rownames: possibly large number of tumors (samples) with category (cluster) & color assigned +// tbl: a matrix, rownames.length x colnames.lenght, of cluster and color assignments +// representing this data structure +// cluster color +// TCGA.08.0525 Classical chocolate +// ... +// +// strategy: +// get unique cluster/color pairs (far fewer of these, typically, than sample ids (tbl rows). +// each sample named in the tbl, and also found in the network, will get a "category" (aka "cluster") +// attribute assigned to it near the end of this function. +// first, however, cyjs/css style rules are handcrafted, one for unique cluster value, and one +// for each cluster value if the node is selected. + function applyTumorCategorization(msg) { console.log("=== applyTumorCategorization"); + var tumorsInGraph = cwMarkers.nodes("[nodeType='patient']"); var tumorsInTable = msg.payload.rownames; var tbl = msg.payload.tbl; var categoryRules = {}; - tbl.forEach(function(row){categoryRules[row[0]] = row[1];}); + // this forEach loop inelegantly reduces many rows to a unique set + // by overwriting, e.g., categoryRules["G-CIMP"] = "purple" each of + // the time it is seen. this inefficiency could be eliminated by + // sending across just the unique rules from R as a payload field + // (and also removing the color column from tbl). + + tbl.forEach(function(row){categoryRules[row[0]] = row[1];}); - /* jshint ignore:start */ - //debugger; - /* jshint ignore:end */ categoryRuleNames = Object.keys(categoryRules); + // e.g. ["G-CIMP", "Classical", "null", "Proneural", "Neural", "Mesenchymal"] categoryRuleNames.filter(function(name){return name !== "null";}); categoryRuleNames.filter(function(name){return name !== null;}); var newRules = []; + // translate the categoryRules into cyjs/css style rules, which + // look like this: + // {"selector":"node[category='Classical']","style":{"background-color":"chocolate"}} + // {"selector":"node[category='Classical']:selected", + // "style":{"border-color":"red","background-color":"chocolate","border-width":"10px"}}" + categoryRuleNames.forEach(function(name){ var selector = "node[category='" + name + "']"; color=categoryRules[name]; @@ -1829,6 +1831,10 @@ hub.logEventOnServer(thisModulesName, "markersApplyTumorCategorization", "data received", ""); + // iterate across the tumor ('patient') nodes, add a category attribute, assign + // a cluster value from the tbl, which will select one of the style rules just + // created above. + console.log("starting tumorsInGraph.forEach"); cwMarkers.batch(function() { tumorsInGraph.forEach(function(node, index){ @@ -1836,7 +1842,6 @@ var indexInTable = tumorsInTable.indexOf(nodeID); if(indexInTable >= 0){ var cluster = tbl[indexInTable][0]; - var color = tbl[indexInTable][1]; node.data({category: cluster}); } else{ @@ -1847,6 +1852,9 @@ console.log("ending tumorsInGraph.forEach"); + // get a copy of the current style, remove any old node-category style rules, add the new ones + // set this new style + var oldStyle = cwMarkers.style().json(); // remove any pre-existing node category rules var oldStyleClean = oldStyle.filter(function(e){return(e.selector.indexOf("node[category"));}); @@ -1984,40 +1992,6 @@ hub.raiseTab(thisModulesOutermostDiv); } // handleIncomingIdentifiers -//---------------------------------------------------------------------------------------------------- - // run all that should happen when this module receives an incoming selection of patientIDs -function demoMarkersIncomingSelectionOfIDs() -{ - - names = ["TCGA.06.0210", "TCGA.02.0106", "TCGA.02.0111", - "TCGA.06.0194", "TCGA.06.0164", "TCGA.06.0409", "TCGA.02.0004", - "TCGA.02.0051", "TCGA.08.0390", "TCGA.02.0025", "TCGA.08.0392", - "TCGA.02.0079", "TCGA.12.0620", "TCGA.08.0373", "TCGA.06.0645", - "TCGA.06.0192", "TCGA.12.0776", "TCGA.12.0778", "TCGA.06.0750", - "TCGA.06.0878", "TCGA.14.0789", "TCGA.06.0881", "BCL11A", - "BRCA1", "MDM2", "PIK3R1", "ABCA1", "CDK6", "CNTRL", "FH", - "IFNA1", "LMO2", "PRKCA", "RELA", "STK11", "ZEB1", "CCNB1IP1", - "CREB3L1", "GDF2", "OR4K2", "PRKCH", "WAS"]; - - subset = []; - for(var i=0; i < 10; i++) - subset.push(names[getRandomInt(0, names.length -1)]); - - selectNodes(subset); - -} // demoIncomingSelectionOfPatientIDs -//---------------------------------------------------------------------------------------------------- -function allNodeIDs() -{ - ids = []; - allNodes = cwMarkers.nodes(); - - for(i=0; i < allNodes.length; i++) - ids.push(allNodes[i].data("id")); - - return(ids); - -} // allNodeIDs //---------------------------------------------------------------------------------------------------- function showEdges() { @@ -2265,7 +2239,7 @@ } // selectNodes //---------------------------------------------------------------------------------------------------- - // todo: build up the filter string first, then send it all at once +// todo: build up the filter string first, then send it all at once function selectNodesByID(nodeIDs) { if(typeof(nodeIDs) == "string") // trap scalar, but expect and support arrays @@ -2320,8 +2294,11 @@ cwMarkers.filter("edge[edgeType='chromosome']").style({"curve-style": "bezier"}); cwMarkers.filter("edge[edgeType='chromosome']").show(); cwMarkers.nodes().unselect(); - // map current node degree into a node attribute of that name - cwMarkers.nodes().map(function(node){node.data({degree: node.degree(), trueWidth: node.width(), trueHeight: node.height()});}); + // map current node degree into a node attribute of that name, + // save the initial width and height to restore values after zooming. + cwMarkers.nodes().map(function(node){node.data({degree: node.degree(), + trueWidth: node.width(), + trueHeight: node.height()});}); var edgeTypes = hub.uniqueElementsOfArray(cwMarkers.edges().map(function(edge){ return(edge.data("edgeType"));} @@ -2946,6 +2923,241 @@ moduleTests.push(markersTester); +//---------------------------------------------------------------------------------------------------- +var BlankTabModule = (function () { + + var blankTabDiv; + var controlsDiv; + var outputDiv; + + var testButton; + + var sendSelectionsMenu; + + var thisModulesName = "blankTab"; + var thisModulesOutermostDiv = "blankTabDiv"; + + var sendSelectionsMenuTitle = "Send selection..."; + + // sometimes a module offers multiple selection destinations + // but usually just the one entry point + var selectionDestinations = [thisModulesName]; + // make sure to register, eg, + // hub.addMessageHandler("sendSelectionTo_blankTab", handleSelections); + +//-------------------------------------------------------------------------------------------- +function initializeUI() +{ + $(window).resize(handleWindowResize); + + blankTabDiv = $("#blankTabDiv"); + controlsDiv = $("#blankTabControlsDiv"); + outputDiv = $("#blankTabOutputDiv"); + + testButton = $("#testBlankTabButton"); + testButton.click(runTests); + + sendSelectionsMenu = hub.configureSendSelectionMenu("#blankTabSendSelectionsMenu", + selectionDestinations, + sendSelections, + sendSelectionsMenuTitle); + + handleWindowResize(); + +} // initializeUI +//---------------------------------------------------------------------------------------------------- +function handleWindowResize() +{ + blankTabDiv.width($(window).width() * 0.95); + blankTabDiv.height($(window).height() * 0.90); // leave room for tabs above + + controlsDiv.width(blankTabDiv.width()); // * 0.95); + controlsDiv.height("100px"); + + outputDiv.width(blankTabDiv.width()); // * 0.95); + outputDiv.height(blankTabDiv.height() - 130); + +} // handleWindowResize +//-------------------------------------------------------------------------------------------- +function sendSelections(event) +{ + var destination = sendSelectionsMenu.val(); + + var cmd = "sendSelectionTo_" + destination; + var dummySelections = ["dummy selection 1", "dummy selection 2"]; + + payload = {value: dummySelections, count: dummySelections.length, + source: thisModulesName}; + + var newMsg = {cmd: cmd, callback: "", status: "request", payload: payload}; + + // restore default (informational) title of the menu + sendSelectionsMenu.val(sendSelectionsMenuTitle); + + hub.send(JSON.stringify(newMsg)); + +} // sendSelections +//-------------------------------------------------------------------------------------------- +function handleSelections(msg) +{ + hub.enableTab(thisModulesOutermostDiv); + hub.raiseTab(thisModulesOutermostDiv); + var msgAsString = JSON.stringify(msg.payload); + + outputDiv.html("
" + msgAsString + " 0
+  var patientHistoryTabPresent = $("#patientHistoryDiv").length > 0
+
+  if(!(datasetsTabPresent && patientHistoryTabPresent)){
+     alert("Need both datasets & patientHistory tabs for QUnit testing");
+     return;
+     } // check for other needed tabs
+
+   outputDiv.css({display: "block"});
+
+   QUnit.test('choose DEMOdz dataset', function(assert) {
+      hub.raiseTab("datasetsDiv");
+      var desiredDataset = "DEMOdz";
+      var dzNames = $("#datasetMenu option").map(function(opt){return this.value})
+
+      if($.inArray(desiredDataset, dzNames) < 0){
+         alert("cannot run tests:  " + desiredDataset + " dataset not loaded");
+         return;
+         }
+
+      $("#datasetMenu").val(desiredDataset)
+      $("#datasetMenu").trigger("change");
+
+      var done1 = assert.async();
+      var done2 = assert.async();
+      var done3 = assert.async();
+      assert.expect(3);
+
+      setTimeout(function(){
+         assert.equal($("#datasetMenu").val(), desiredDataset);  done1();
+         assert.ok($("#datasetsManifestTable tr").length >= 10); done2();
+         assert.equal($("#datasetsManifestTable tbody tr").eq(0).find("td").eq(0).text(), 
+                      "mRNA expression"); done3();
+         testLoadPatientHistoryTable();
+         }, 5000);
+      });
+
+} // runTests
+//----------------------------------------------------------------------------------------------------
+function testLoadPatientHistoryTable()
+{
+   QUnit.test('load patient history table', function(assert) {
+       console.log("=============  starting load pt tbl test");
+       hub.enableButton($("#selectDatasetButton"));
+       $("#selectDatasetButton").trigger("click");
+       var done1 = assert.async();
+       assert.expect(1);
+
+       setTimeout(function(){
+          console.log("-- starting async check");
+          assert.equal($("#patientHistoryTable tr").length, 21);
+          done1();
+          testSelectLongSurvivors();
+          }, 5000);
+       });
+
+} // testLoadPatientHistoryTable
+//----------------------------------------------------------------------------------------------------
+function testSelectLongSurvivors()
+{
+   QUnit.test('testSelectLongSurvivors', function(assert) {
+      tbl = $("#patientHistoryTable").DataTable();
+      $("#survivalMinSliderReadout").text("8");  // just two DEMOdz patients lived > 8 years
+      tbl.draw()
+      hub.raiseTab("patientHistoryDiv");
+      assert.expect(1);
+      var done1 = assert.async()
+      setTimeout(function(){
+         assert.equal($("#patientHistoryTable tbody tr").length, 2);
+         done1();
+         testSendToBlankTab();
+         }, 5000);
+      });
+
+} // testSelectLongSurvivors
+//----------------------------------------------------------------------------------------------------
+function testSendToBlankTab()
+{
+   QUnit.test('testSendToBlankTab', function(assert) {
+      $("#patientHistorySendSelectionsMenu").val("blankTab");
+      $("#patientHistorySendSelectionsMenu").trigger("change");
+      assert.expect(0);   // tests (assertions) in next function, testContentsOfBlankTab
+      setTimeout(function(){
+         hub.raiseTab("blankTabDiv");
+         testContentsOfBlankTab();
+         }, 5000);
+      });
+
+} // testSendToBlankTab
+//----------------------------------------------------------------------------------------------------
+function testContentsOfBlankTab()
+{
+   QUnit.test('testContensOfBlankTab', function(assert) {
+      assert.equal($("#blankTabOutputDiv").text(), 
+                   '{"value":["TCGA.02.0114","TCGA.08.0344"],"count":2,"source":"patient history module"}');
+      $("#testingOutputDiv").css({display: "block"});
+      });
+
+} // testContentsOfBlankTab
+//----------------------------------------------------------------------------------------------------
+// query the oncoscape server for user id.  the callback then makes a local (that is,
+// Module-specific) decision to run this module's automated tests based upon that id
+//
+function runAutomatedTestsIfAppropriate()
+{
+   var msg = {cmd: "getUserId",  callback: "blankTabAssessUserIdForTesting",
+              status: "request", payload: ""};
+
+   hub.send(JSON.stringify(msg));
+
+} // runAutomatedTestsIfAppropriate
+//----------------------------------------------------------------------------------------------------
+function assessUserIdForTesting(msg)
+{
+   var userID = msg.payload;
+   console.log("blankTab/Module.js assesUserIdForTesting: " + userID)
+
+   if(userID.indexOf("autoTest") === 0){
+      console.log("blankTab/Module.js running tests for user " + userID)
+      runTests();
+      }
+
+} // assessUserIdForTesting
+//----------------------------------------------------------------------------------------------------
+function initializeModule()
+{
+   hub.registerSelectionDestination(selectionDestinations, thisModulesOutermostDiv);
+   hub.addOnDocumentReadyFunction(initializeUI);
+   hub.addMessageHandler("sendSelectionTo_blankTab", handleSelections);
+   hub.addMessageHandler("blankTabAssessUserIdForTesting", assessUserIdForTesting)
+   hub.addSocketConnectedFunction(runAutomatedTestsIfAppropriate);
+   hub.enableTab(thisModulesOutermostDiv);
+
+} // initializeModule
+//----------------------------------------------------------------------------------------------------
+return{
+   init: initializeModule
+   }; // BlankTabModule return value
+
+//----------------------------------------------------------------------------------------------------
+}); // BlankTabModule
+
+blankTabModule = BlankTabModule();
+blankTabModule.init();
+
+
 
 
 
@@ -2956,6 +3168,7 @@
      
  • Datasets
  • Markers
  • Tests
  • +
  • Blank Tab
  • + + +
    + + +
    + + +
    + + + +
    +
    + + + +
    + diff --git a/Oncoscape/inst/scripts/markersAndSamples/index.pre b/Oncoscape/inst/scripts/markersAndSamples/index.pre index e5746ecbb..c328d8cb9 100644 --- a/Oncoscape/inst/scripts/markersAndSamples/index.pre +++ b/Oncoscape/inst/scripts/markersAndSamples/index.pre @@ -13,6 +13,7 @@ include(../tabsApp/code.js) include(../datasets/Module.js) include(../markersAndSamples/Module.js) include(../markersAndSamples/Test.js) +include(../blankTab/Module.js) @@ -23,11 +24,13 @@ include(../markersAndSamples/Test.js)
  • Datasets
  • Markers
  • Tests
  • +
  • Blank Tab
  • include(../datasets/widget.html) include(../markersAndSamples/widget.html) include(../markersAndSamples/test.html) +include(../blankTab/widget.html) diff --git a/Oncoscape/inst/scripts/markersAndSamples/log.2015-11-13.18:16:49.RData b/Oncoscape/inst/scripts/markersAndSamples/log.2015-11-13.18:16:49.RData deleted file mode 100644 index df2ba961a4cfca01ac672d6936ff0dc9a7bf70ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2262 zcmb7+XFMB<0>u%P+geYI-iyjZ)7rFJH7;pU8Y{Ibs!fP>6*orh5~HONqehKbRV^hH z^^6)#R1_6zQ$^GWN)p73b;q~&`@Q$!o)71LKAdyF_@B7`7J!i-X=mpy)78a&E=GJX z#$v%TUBVhjPi}k$*pQSxpOmPJK1(;Vr3%cv2jHcuK6%wOSd92qUA<;*?P7bQhT2`? z<@DIeY4t7fTXWv1nlJOgE5_H))9+Dap~AuzPnPVp2^zQ~!Se%(d05DbETpxOufu|K z+euW^YnyU=g9r6yjQOJx2gZ?x$s%!+JybSnzj*X!J4#6~t~He(FeH{Yec!fk)Ko|N zyA0CLR41&qA2Ow>5`Yj_&k9H(JTSnE?kiz6?*O@0DMRol4s06}~aD3Ny zP<%K^L<(ZmbNh0pz(0h%a&9pTH}KP;nJ`NN7%%FR-+lA+BM7E?(H8(useTC4{MUZ< z3E|}5Sca@ozM2$xamNnv!+TGmpV8o;Q=MohI%<5?+VX#b#w6HPTxZQ2(tAqj8c^ER z7uW-L4QdW=e6Lij9qu}TyW-+jRFS|buch19) zv1m#zWg679=!+lLbHAq?%AUNWAmIBzX9lMzn#eR1(gY`wH$2})@O7mU8?s_!-wJI# zW&!fd4BG|gR%cV|b3&%*gx}Z8?Ah(A@VTJ52Kq72)apSx#ZjHs3jQ^JTRYTe>NKv- zC_FfJxPMw$EgYkVD16M;IQZ^dM%nA}8kn!gN1d|T{|dsLmc>H>9gWpMby|Y-c14rY z?Rh^QL<> z^}?&vqN**qeOn`RJs`p}l8yPh9>ZSO{h53Xm@De`=&g=&O^KoFcqo)%Lm zcg3ac)d(qizVx9*E|<(_@`erOcZ;l?o&SIX%)d#9@@nPzBk5X2hx$!RqV<$5)8QJS z;cI=Vz{V@HO)FojLwO##NR3%?@T&Kn$Gh}r)ASu@2WNCKE16`5; zzTYHb-0K=*dg0C_k6({}sJB<8#DO$jZ%SYEZYdX>8YHFE-R0Coy=x4Th*nKQr0VR- zm>TFL>#ptQCqTPCbbl3Dmz>DY5oGE<4N4#8FfaJApnC0EktC99pUnDDza}W~pn*V! zw|t5&f`4r8X{iFT`|?h@hi6mI_!+RZ`s-oT)V@50TIXHcW&TsDzyaEsodSKOjh(TU zB7h!e*Wvr*aU^mNadgQq&_rWmtjOHupp&e~1K;d}-rwaJ@+QBa-tn_h9jk)4LFnH8 zRdwd~YGk7>H(gpnuJ>r&LrFYxBR3-kvNv-mPwG}{FlPyQwKR#S2H_(Q*s^GMAZ#M! zPMmeIF3#LjIssF@A;7@}tvN|*XlzMqZ*y+}h=a>OLM5VcY@y&yZ+LImmZCR30f8N> zlrrFBcfC}<`^}*QtG=obgLNzej6Zk3|D_$pBuOv5zISl8vSf3=@dY$n-A7l^|NX(M zJLsExoT4}p&l;4{OVuW|JM@{9)$0(fKf%~3DCF6LWtI+FCv_Rr=J2qM?e8>7p!@-r&=AvMP{i30!=ZUQK9SxH5QgIB+wHHrW)!)j97w7Q|ImQ&dXjQ~~&f6^g zFUUlO2_G5QdfytzTUy=@-1?*t8Bj6vjPOju3=$`&Xq}cx$x0W8DO$k3s3A=*|D522 zhC7;E{_z*X+|1WHOK+pqwRCW8LeF8P-?OL}Zh|6kN|_VCq&W9<|NeXvM8t$b#$ajL z)Wq{+!5XE14lmcdHQog2DFF16t(9xxuVY5JGtEqPU}+f$2e~j@WR_)zT5Wh{rJD!b zv6y1z%6n_A-@_w>>q$BlmXAIcBBZy}?x@DR(pOEr77ykI5x+eGfa>r{S%@|V zBwE!c3|An_M%tCTp&9OBIDL1~2xQ3}^i?_0mcKgLT4A`hn#J>DnSE;d2N-h41|K0{MjFUzXD3GC-l39b*{+$XU%XoZ3J1vksH=B*$A)1blY{niCv4a)m4|SwxvRg`RpzZc$QkB86yT!<9 oXc7OoRrxzYps&Hw-a From 626ec0a04f3c1e75be40064b96b7ec4495b91d38 Mon Sep 17 00:00:00 2001 From: LisaMc Date: Thu, 17 Mar 2016 18:51:35 -0700 Subject: [PATCH 2/5] includes addtl comments - subselect broken --- .../inst/scripts/markersAndSamples/Module.js | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/Oncoscape/inst/scripts/markersAndSamples/Module.js b/Oncoscape/inst/scripts/markersAndSamples/Module.js index 85fefdaa6..372164610 100644 --- a/Oncoscape/inst/scripts/markersAndSamples/Module.js +++ b/Oncoscape/inst/scripts/markersAndSamples/Module.js @@ -1058,29 +1058,6 @@ function displayMarkersNetwork(msg) console.log(" after JSON.parse, json.length: " + json.length); console.log(" about to add json.elements"); cwMarkers.add(json.elements); -<<<<<<< HEAD - cwMarkers.style(json.style); - cwMarkers.edges().hide(); - cwMarkers.filter("edge[edgeType='chromosome']").style({"curve-style": "bezier"}); - cwMarkers.filter("edge[edgeType='chromosome']").show(); - cwMarkers.nodes().unselect(); - // map current node degree into a node attribute of that name, - // save the initial width and height to restore values after zooming. - cwMarkers.nodes().map(function(node){node.data({degree: node.degree(), - trueWidth: node.width(), - trueHeight: node.height()});}); - - var edgeTypes = hub.uniqueElementsOfArray(cwMarkers.edges().map(function(edge){ - return(edge.data("edgeType"));} - )); - updateEdgeSelectionWidget(edgeTypes); // preserve only known edgeTypes - cwMarkers.fit(20); - - var defaultLayout = JSON.stringify(cwMarkers.nodes().map(function(n){ - return({id:n.id(), position:n.position()});})); - localStorage.markersDefault = defaultLayout; - defaultPatientNodeColor = cwMarkers.nodes("[nodeType='patient']").style("background-color"); -======= // map current node degree into a node attribute of that name }); @@ -1108,7 +1085,6 @@ function displayMarkersNetwork(msg) return({id:n.id(), position:n.position()});})); localStorage.markersDefault = defaultLayout; defaultPatientNodeColor = cwMarkers.nodes("[nodeType='patient']").style("background-color"); ->>>>>>> develop hub.logEventOnServer(thisModulesName, "display markers network", "complete", ""); From 0690be826943fb42f28bb8ecae09dfaaabb26731 Mon Sep 17 00:00:00 2001 From: LisaMc Date: Fri, 18 Mar 2016 17:21:17 -0700 Subject: [PATCH 3/5] subselect nodes ignoring single quote character fixed with space after equal sign --- Oncoscape/inst/scripts/markersAndSamples/Module.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Oncoscape/inst/scripts/markersAndSamples/Module.js b/Oncoscape/inst/scripts/markersAndSamples/Module.js index 372164610..6e0cd88dd 100644 --- a/Oncoscape/inst/scripts/markersAndSamples/Module.js +++ b/Oncoscape/inst/scripts/markersAndSamples/Module.js @@ -441,8 +441,11 @@ function defaultStyle() // function subSelectNodes() { - var selectedPatientNodes = cwMarkers.nodes("node[nodeType='patient']:selected"); - var categories = jQuery.unique(selectedPatientNodes.map(function(e){return e.data("category");})); + + var selectedPatientNodes = cwMarkers.nodes("node[nodeType= 'patient']:selected"); + var categories = jQuery.unique( + selectedPatientNodes.map(function(e){ + return e.data("category");})); var colors = jQuery.unique(selectedPatientNodes.map(function(node){return (node.style("background-color"));})); @@ -605,6 +608,7 @@ function applyTumorCategorization(msg) var indexInTable = tumorsInTable.indexOf(nodeID); if(indexInTable >= 0){ var cluster = tbl[indexInTable][0]; + var color = tbl[indexInTable][1]; node.data({category: cluster}); } else{ From 011261a19d456759e22fc47e57057a71894070f7 Mon Sep 17 00:00:00 2001 From: Jenny Zhang Date: Wed, 23 Mar 2016 12:27:16 -0700 Subject: [PATCH 4/5] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f9401c49..82d8fd572 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -[![Circle CI](https://circleci.com/gh/FredHutch/Oncoscape/tree/develop.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/FredHutch/Oncoscape/tree/develop) # Oncoscape +[![Circle CI](https://circleci.com/gh/FredHutch/Oncoscape/tree/develop.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/FredHutch/Oncoscape/tree/develop) + [![Join the chat at https://gitter.im/FredHutch/Oncoscape](https://badges.gitter.im/FredHutch/Oncoscape.svg)](https://gitter.im/FredHutch/Oncoscape?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Oncoscape is a web application that hosts an integrated suite of analysis tools for users to explore hypotheses related to molecular and clinical data in order to better understand cancer biology and treatment options. From 5a321b64fea9e5a724797ae6f3985469d170eb47 Mon Sep 17 00:00:00 2001 From: LisaMc Date: Wed, 23 Mar 2016 21:47:24 -0700 Subject: [PATCH 5/5] handling quotation reading issues for subselect --- Oncoscape/inst/scripts/markersAndSamples/Module.js | 4 ++-- Oncoscape/inst/scripts/markersAndSamples/index.pre | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Oncoscape/inst/scripts/markersAndSamples/Module.js b/Oncoscape/inst/scripts/markersAndSamples/Module.js index 6e0cd88dd..5457cdf51 100644 --- a/Oncoscape/inst/scripts/markersAndSamples/Module.js +++ b/Oncoscape/inst/scripts/markersAndSamples/Module.js @@ -441,8 +441,8 @@ function defaultStyle() // function subSelectNodes() { - - var selectedPatientNodes = cwMarkers.nodes("node[nodeType= 'patient']:selected"); +// var selectedPatientNodes = cwMarkers.nodes("node[nodeType='patient']:selected"); comment necessary to handle quotation issue + var selectedPatientNodes = cwMarkers.nodes("node[nodeType='patient']:selected"); var categories = jQuery.unique( selectedPatientNodes.map(function(e){ return e.data("category");})); diff --git a/Oncoscape/inst/scripts/markersAndSamples/index.pre b/Oncoscape/inst/scripts/markersAndSamples/index.pre index 7ba6e0ed2..c328d8cb9 100644 --- a/Oncoscape/inst/scripts/markersAndSamples/index.pre +++ b/Oncoscape/inst/scripts/markersAndSamples/index.pre @@ -8,6 +8,7 @@ include(../hub/Module.js) var hub = HubModule(); hub.start(); +include(../testManager/Module.js) include(../tabsApp/code.js) include(../datasets/Module.js) include(../markersAndSamples/Module.js)