UNPKG

grnsight

Version:

Web app and service for visualizing models of gene regulatory networks

1,037 lines (920 loc) 41.1 kB
import { drawGraph, updaters } from "./graph"; import { uploadState } from "./upload"; import { displayWarnings, displayPPINodeColorWarning } from "./warnings"; import { max } from "d3-array"; import { grnState } from "./grnstate"; import { HOST_SITE, FORCE_GRAPH, GRID_LAYOUT, GREY_EDGES_DASHED_MENU, GREY_EDGES_DASHED_SIDEBAR, MIN_EDGE_WEIGHT_NORMALIZATION, MAX_EDGE_WEIGHT_NORMALIZATION, GREY_EDGE_THRESHOLD_MENU, GREY_EDGE_THRESHOLD_SLIDER_SIDEBAR, GREY_EDGE_THRESHOLD_TEXT_SIDEBAR, WEIGHTS_SHOW_MOUSE_OVER_MENU, WEIGHTS_SHOW_ALWAYS_MENU, WEIGHTS_HIDE_MENU, WEIGHTS_SHOW_MOUSE_OVER_SIDE, WEIGHTS_SHOW_ALWAYS_SIDE, WEIGHTS_HIDE_SIDE, WEIGHTS_SHOW_MOUSE_OVER_CLASS, WEIGHTS_SHOW_ALWAYS_CLASS, WEIGHTS_HIDE_CLASS, SHOW_WEIGHTS_MOUSEOVER, SHOW_ALL_WEIGHTS, HIDE_ALL_WEIGHTS, COLOR_EDGES_MENU, COLOR_EDGES_SIDEBAR, ACTIVE_COLOR_OPTION, GRAVITY_LENGTH_WITHOUT_ZERO, LOCK_SLIDERS_MENU, LOCK_SLIDERS_BUTTON, RESET_SLIDERS_SIDEBAR, RESET_SLIDERS_MENU, UNDO_SLIDERS_RESET_SIDEBAR, UNDO_SLIDERS_RESET_MENU, LINK_DIST_CLASS, LINK_DIST_SLIDER_SIDEBAR, LINK_DIST_MENU, LINK_DIST_VALUE, CHARGE_CLASS, CHARGE_SLIDER_SIDEBAR, CHARGE_MENU, CHARGE_VALUE, LAYOUT_SIDEBAR_PANEL, NODE_COLORING_MENU, NODE_COLORING_TOGGLE_MENU, NODE_COLORING_MENU_CLASS, NODE_COLORING_NAVBAR_OPTIONS, NODE_COLORING_SIDEBAR_BODY, NODE_COLORING_SIDEBAR_PANEL, NODE_COLORING_SIDEBAR_HEADER_LINK, NODE_COLORING_TOGGLE_SIDEBAR, AVG_REPLICATE_VALS_TOP_MENU, AVG_REPLICATE_VALS_TOP_SIDEBAR, AVG_REPLICATE_VALS_BOTTOM_MENU, AVG_REPLICATE_VALS_BOTTOM_SIDEBAR, LOG_FOLD_CHANGE_MAX_VALUE_MENU, LOG_FOLD_CHANGE_MAX_VALUE_SIDEBAR_INPUT, MINIMUM_MAX_LOG_FOLD_CHANGE, MAXIMUM_MAX_LOG_FOLD_CHANGE, DEFAULT_MAX_LOG_FOLD_CHANGE, TOP_DATASET_SELECTION_SIDEBAR, TOP_DATASET_SELECTION_MENU, BOTTOM_DATASET_SELECTION_SIDEBAR, BOTTOM_DATASET_SELECTION_MENU, LOG_FOLD_CHANGE_MAX_VALUE_CLASS, LOG_FOLD_CHANGE_MAX_VALUE_SIDEBAR_BUTTON, LOG_FOLD_CHANGE_MAX_VALUE_HEADER, MAX_NUM_CHARACTERS_DROPDOWN, ENDS_IN_EXPRESSION_REGEXP, ZOOM_CONTROL, ZOOM_DISPLAY_MIDDLE, ZOOM_ADAPTIVE_MAX_SCALE, ZOOM_INPUT, ZOOM_SLIDER, EXPORT_WEIGHTED_CLASS, EDGE_WEIGHT_MENU_CLASS, EDGE_WEIGHT_SIDEBAR, EDGE_WEIGHT_SIDEBAR_HEADER_LINK, SPECIES_DISPLAY, EXPRESSION_DB_LOADER, EXPRESSION_DB_LOADER_TEXT, SPECIES_BUTTON_CRESS, SPECIES_BUTTON_FLY, SPECIES_BUTTON_HUMAN, SPECIES_BUTTON_MOUSE, SPECIES_BUTTON_NEMATODE, SPECIES_BUTTON_YEAST, VIEWPORT_FIT, VIEWPORT_S, VIEWPORT_M, VIEWPORT_L, VIEWPORT_SIZE_S_DROPDOWN, VIEWPORT_SIZE_M_DROPDOWN, VIEWPORT_SIZE_L_DROPDOWN, VIEWPORT_SIZE_FIT_DROPDOWN, VIEWPORT_SIZE_S_SIDEBAR, VIEWPORT_SIZE_M_SIDEBAR, VIEWPORT_SIZE_L_SIDEBAR, VIEWPORT_SIZE_FIT_SIDEBAR, VIEWPORT_INIT, NETWORK_MODE_DROPDOWN, NETWORK_MODE_CLASS, NETWORK_MODE_PROTEIN_PHYS, NETWORK_MODE_GRN, EXPORT_TO_UNWEIGHTED_GML_MENU, NETWORK_GRN_MODE, NETWORK_PPI_MODE, // EXPRESSION_SOURCE, } from "./constants"; import { queryExpressionDatabase } from "./api/grnsight-api.js"; // In this transitory state, updateApp might get called before things are completely set up, so for now // we define this wrapper function that guards against uninitialized values. queryExpressionDatabase({type:"ExpressionDatasets"}).then(function (response) { grnState.database = response; }).catch(function (error) { console.log(error.stack); console.log(error.name); console.log(error.message); }); const refreshApp = () => { if (uploadState && uploadState.currentWorkbook) { drawGraph(uploadState.currentWorkbook); } }; const displayworkbook = (workbook, name) => { uploadState.currentWorkbook = workbook; $("#graph-metadata").html(workbook.genes.length + " nodes<br>" + workbook.links.length + " edges"); if (workbook.warnings.length > 0) { displayWarnings(workbook.warnings); } $("#fileName").text(name); // Set the name of the file to display in the top bar $("input[type='range']").off("input"); // I have no idea why I do this. Investigate later. }; // Value Validators export const valueValidator = (min, max, value) => { return Math.min(max, Math.max(min, value)); }; const edgeWeightNormalizationInputValidation = value => { return value === "" ? "" : valueValidator(MIN_EDGE_WEIGHT_NORMALIZATION, MAX_EDGE_WEIGHT_NORMALIZATION, value); }; const synchronizeNormalizationValues = value => { var validated = edgeWeightNormalizationInputValidation(value); $("#normalization-max").val(validated); $("#edge-weight-normalization-factor-menu").val(validated); }; const grayEdgeInputValidator = value => { return valueValidator(0, 100, value); }; const logFoldChangeMaxValueInputValidation = value => { if (value === "" || value === "0") { return DEFAULT_MAX_LOG_FOLD_CHANGE; } else if (value < MINIMUM_MAX_LOG_FOLD_CHANGE) { return MINIMUM_MAX_LOG_FOLD_CHANGE; } else if (value > MAXIMUM_MAX_LOG_FOLD_CHANGE) { return MAXIMUM_MAX_LOG_FOLD_CHANGE; } else { return value; } }; // Weight Visualization Function const showEdgeWeightOptions = () => { $(EDGE_WEIGHT_MENU_CLASS).removeClass("disabled"); $(EXPORT_WEIGHTED_CLASS).removeClass("startDisabled").removeClass("disabled"); $(EDGE_WEIGHT_SIDEBAR).removeClass("disabled"); $(EDGE_WEIGHT_SIDEBAR_HEADER_LINK).attr("data-toggle", "collapse"); }; const hideEdgeWeightOptions = () => { $(EDGE_WEIGHT_MENU_CLASS).addClass("disabled"); $(EXPORT_WEIGHTED_CLASS).removeClass("startDisabled").addClass("disabled"); $(EDGE_WEIGHT_SIDEBAR).addClass("disabled"); $(EDGE_WEIGHT_SIDEBAR_HEADER_LINK).attr("data-toggle", ""); }; const synchronizeGrayEdgeValues = value => { var validatedInput = grayEdgeInputValidator(value); $(GREY_EDGE_THRESHOLD_MENU).val(validatedInput); $(GREY_EDGE_THRESHOLD_TEXT_SIDEBAR).text(validatedInput + "%"); $(GREY_EDGE_THRESHOLD_SLIDER_SIDEBAR).val(validatedInput / 100); }; const synchronizeShowWeightsMouseover = () => { $(WEIGHTS_SHOW_MOUSE_OVER_MENU + " span").addClass("glyphicon-ok"); $(WEIGHTS_SHOW_ALWAYS_MENU + " span").removeClass("glyphicon-ok"); $(WEIGHTS_HIDE_MENU + " span").removeClass("glyphicon-ok"); $(WEIGHTS_SHOW_MOUSE_OVER_SIDE).prop("checked", "checked"); $(WEIGHTS_SHOW_ALWAYS_SIDE).removeProp("checked"); $(WEIGHTS_HIDE_SIDE).removeProp("checked"); $(WEIGHTS_SHOW_MOUSE_OVER_CLASS).addClass("selected"); $(WEIGHTS_SHOW_ALWAYS_CLASS).removeClass("selected"); $(WEIGHTS_HIDE_CLASS).removeClass("selected"); }; const synchronizeShowAllWeights = () => { $(WEIGHTS_SHOW_MOUSE_OVER_MENU + " span").removeClass("glyphicon-ok"); $(WEIGHTS_SHOW_ALWAYS_MENU + " span").addClass("glyphicon-ok"); $(WEIGHTS_HIDE_MENU + " span").removeClass("glyphicon-ok"); $(WEIGHTS_SHOW_MOUSE_OVER_SIDE).removeProp("checked"); $(WEIGHTS_SHOW_ALWAYS_SIDE).prop("checked", "checked"); $(WEIGHTS_HIDE_SIDE).removeProp("checked"); $(WEIGHTS_SHOW_MOUSE_OVER_CLASS).removeClass("selected"); $(WEIGHTS_SHOW_ALWAYS_CLASS).addClass("selected"); $(WEIGHTS_HIDE_CLASS).removeClass("selected"); }; const synchronizeHideAllWeights = () => { $(WEIGHTS_SHOW_MOUSE_OVER_MENU + " span").removeClass("glyphicon-ok"); $(WEIGHTS_SHOW_ALWAYS_MENU + " span").removeClass("glyphicon-ok"); $(WEIGHTS_HIDE_MENU + " span").addClass("glyphicon-ok"); $(WEIGHTS_SHOW_MOUSE_OVER_SIDE).removeProp("checked"); $(WEIGHTS_SHOW_ALWAYS_SIDE).removeProp("checked"); $(WEIGHTS_HIDE_SIDE).prop("checked", "checked"); $(WEIGHTS_SHOW_MOUSE_OVER_CLASS).removeClass("selected"); $(WEIGHTS_SHOW_ALWAYS_CLASS).removeClass("selected"); $(WEIGHTS_HIDE_CLASS).addClass("selected"); }; // Viewport const synchronizeViewportSizeSmall = () => { $(VIEWPORT_SIZE_S_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_M_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_L_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_FIT_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_S_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_M_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_L_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_FIT_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_S_SIDEBAR).prop("checked", "checked"); $(VIEWPORT_SIZE_S_DROPDOWN + " span").addClass("glyphicon-ok"); }; const synchronizeViewportSizeMedium = () => { $(VIEWPORT_SIZE_S_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_M_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_L_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_FIT_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_S_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_M_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_L_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_FIT_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_M_SIDEBAR).prop("checked", "checked"); $(VIEWPORT_SIZE_M_DROPDOWN + " span").addClass("glyphicon-ok"); }; const synchronizeViewportSizeLarge = () => { $(VIEWPORT_SIZE_S_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_M_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_L_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_FIT_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_S_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_M_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_L_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_FIT_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_L_SIDEBAR).prop("checked", "checked"); $(VIEWPORT_SIZE_L_DROPDOWN + " span").addClass("glyphicon-ok"); }; const synchronizeViewportSizeFit = () => { $(VIEWPORT_SIZE_S_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_M_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_L_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_FIT_DROPDOWN + " span").removeClass("glyphicon-ok"); $(VIEWPORT_SIZE_S_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_M_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_L_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_FIT_SIDEBAR).removeProp("checked"); $(VIEWPORT_SIZE_FIT_SIDEBAR).prop("checked", "checked"); $(VIEWPORT_SIZE_FIT_DROPDOWN + " span").addClass("glyphicon-ok"); }; const updateViewportSize = (currentValue) => { // These values are bound to the layout dimensions of the GRNsight website. const WIDTH_OFFSET = 250; const HEIGHT_OFFSET = 53; let container = $(".grnsight-container"); // from jquery const fitContainer = dimensions => { if (!dimensions) { return; // First call; the next one should have dimensions filled in. } const fitWidth = dimensions.width - WIDTH_OFFSET; const fitHeight = dimensions.height - dimensions.top - HEIGHT_OFFSET; if (fitWidth !== container.width() || fitHeight !== container.height()) { container.css({ width: fitWidth, height: fitHeight }); } }; const fitContainerToWindow = () => { fitContainer({ width: $(window).width(), height: $(window).height(), top: 0 }); }; const requestWindowDimensions = () => { // We send a message if we are in an iframe, and manipulate directly if we aren’t. if (window === window.top) { fitContainerToWindow(); } else { window.top.postMessage("dimensions", HOST_SITE); } }; let grnsightContainerClass = `grnsight-container ${currentValue}`; if (!container.hasClass(currentValue)) { container.attr("class", grnsightContainerClass); if (currentValue === VIEWPORT_FIT) { requestWindowDimensions(); } else { container.css({ width: "", height: "" }); } } // Added synchronization if (currentValue === VIEWPORT_S) { synchronizeViewportSizeSmall(); } else if (currentValue === VIEWPORT_M) { synchronizeViewportSizeMedium(); } else if (currentValue === VIEWPORT_L) { synchronizeViewportSizeLarge(); } else if (currentValue === VIEWPORT_FIT) { fitContainer(grnState.dimensions); synchronizeViewportSizeFit(); } else if (currentValue === VIEWPORT_INIT) { // First time around: initialize. requestWindowDimensions(); } }; // Expression DB Functions const startLoadingIcon = function () { $(EXPRESSION_DB_LOADER).css("display", "block"); $(EXPRESSION_DB_LOADER_TEXT).css("display", "block"); }; const stopLoadingIcon = function () { $(EXPRESSION_DB_LOADER).css("display", "none"); $(EXPRESSION_DB_LOADER_TEXT).css("display", "none"); }; const enableNodeColoringUI = function () { grnState.nodeColoring.nodeColoringEnabled = true; $(LOG_FOLD_CHANGE_MAX_VALUE_CLASS).removeClass("hidden"); $(LOG_FOLD_CHANGE_MAX_VALUE_SIDEBAR_BUTTON).removeClass("hidden"); $(LOG_FOLD_CHANGE_MAX_VALUE_HEADER).removeClass("hidden"); }; const adjustGeneNameForExpression = function (gene) { const geneName = gene.name; return grnState.workbook.meta.data.workbookType === NETWORK_PPI_MODE && geneName.endsWith("p") ? geneName.slice(0, -1) : geneName; }; const loadExpressionDatabase = function (isTopDataset) { const dataset = isTopDataset ? grnState.nodeColoring.topDataset : grnState.nodeColoring.bottomDataset; startLoadingIcon(); queryExpressionDatabase({ type: "ExpressionTimePoints", dataset }).then(function (timepointsResponse) { queryExpressionDatabase({ type:"ExpressionData", dataset, genes: grnState.workbook.genes .map(adjustGeneNameForExpression) .join(","), timepoints: timepointsResponse[dataset] }).then(function (response) { if (isTopDataset) { grnState.workbook.expression[grnState.nodeColoring.topDataset] = response; } else { grnState.workbook.expression[grnState.nodeColoring.bottomDataset] = response; } enableNodeColoringUI(); stopLoadingIcon(); updaters.renderNodeColoring(); }).catch(function (error) { console.log(error.stack); console.log(error.name); console.log(error.message); }); }).catch(function (error) { console.log(error.stack); console.log(error.name); console.log(error.message); }); }; // Sliders Functions const updateSliderState = slidersLocked => { const forceGraphDisabled = grnState.graphLayout === GRID_LAYOUT || slidersLocked; if (forceGraphDisabled) { $(RESET_SLIDERS_MENU).parent().addClass("disabled"); $(UNDO_SLIDERS_RESET_MENU).parent().addClass("disabled"); $(LINK_DIST_CLASS).parent().addClass("disabled"); $(CHARGE_CLASS).parent().addClass("disabled"); } else { $(RESET_SLIDERS_MENU).parent().removeClass("disabled"); $(UNDO_SLIDERS_RESET_MENU).parent().removeClass("disabled"); $(LINK_DIST_CLASS).parent().removeClass("disabled"); $(CHARGE_CLASS).parent().removeClass("disabled"); } $(LINK_DIST_SLIDER_SIDEBAR).prop("disabled", forceGraphDisabled); $(CHARGE_SLIDER_SIDEBAR).prop("disabled", forceGraphDisabled); $(RESET_SLIDERS_SIDEBAR).prop("disabled", forceGraphDisabled); if (slidersLocked) { $(`${LOCK_SLIDERS_MENU} span`) .removeClass("invisible") .addClass("glyphicon-ok"); } else { $(`${LOCK_SLIDERS_MENU} span`) .removeClass("glyphicon-ok") .addClass("invisible"); } $(LOCK_SLIDERS_BUTTON).prop("checked", slidersLocked); if (!grnState.showUndoReset) { $(UNDO_SLIDERS_RESET_SIDEBAR).prop("disabled", true); } }; export const modifyChargeParameter = (value) => { grnState.simulation.force("charge").strength(value); grnState.simulation.alpha(1); }; export const modifyLinkDistanceParameter = (value) => { grnState.simulation.force("link").distance(value); grnState.simulation.alpha(1); }; const updateChargeSliderValues = () => { if (grnState.workbook !== null) { modifyChargeParameter(grnState.chargeSlider.currentVal); } $(CHARGE_VALUE).text(grnState.chargeSlider.currentVal); $(CHARGE_MENU).val(grnState.chargeSlider.currentVal); $(CHARGE_SLIDER_SIDEBAR).val(grnState.chargeSlider.currentVal); $(CHARGE_SLIDER_SIDEBAR).html(grnState.chargeSlider.currentVal + ((grnState.chargeSlider.needsAppendedZeros && grnState.chargeSlider.currentVal.toString().length === GRAVITY_LENGTH_WITHOUT_ZERO) ? "0" : "")); }; const updateLinkDistanceSliderValues = () => { if (grnState.workbook !== null) { modifyLinkDistanceParameter(grnState.linkDistanceSlider.currentVal); } $(LINK_DIST_VALUE).text(grnState.linkDistanceSlider.currentVal); $(LINK_DIST_MENU).val(grnState.linkDistanceSlider.currentVal); $(LINK_DIST_SLIDER_SIDEBAR).val(grnState.linkDistanceSlider.currentVal); $(LINK_DIST_SLIDER_SIDEBAR).html(grnState.linkDistanceSlider.currentVal + ((grnState.linkDistanceSlider.needsAppendedZeros && grnState.linkDistanceSlider.currentVal.toString().length === GRAVITY_LENGTH_WITHOUT_ZERO) ? "0" : "")); }; // Grid Layout Functions const expandLayoutSidebar = () => { $(LAYOUT_SIDEBAR_PANEL).addClass("in"); }; const toggleLayout = (on, off) => { if (!$(on).prop("checked")) { $(on).prop("checked", true); $(off).prop("checked", false); $(`${off} span`).removeClass("glyphicon-ok"); $(`${on} span`).addClass("glyphicon-ok"); } }; export const hasExpressionData = (sheets) => { return Object.keys(sheets).some(property => property.match(ENDS_IN_EXPRESSION_REGEXP)); }; const updatetoForceGraph = () => {}; const updatetoGridLayout = () => {}; // Node Coloring Functions const showNodeColoringMenus = () => { $(NODE_COLORING_SIDEBAR_PANEL).removeClass("disabled"); $(NODE_COLORING_SIDEBAR_PANEL).addClass("in"); $(NODE_COLORING_MENU).removeClass("disabled"); $(NODE_COLORING_MENU_CLASS).removeClass("disabled"); $(NODE_COLORING_SIDEBAR_HEADER_LINK).attr("data-toggle", "collapse"); }; const disableNodeColoringMenus = () => { $(NODE_COLORING_SIDEBAR_PANEL).addClass("disabled"); $(NODE_COLORING_SIDEBAR_PANEL).removeClass("in"); $(NODE_COLORING_MENU_CLASS).addClass("disabled"); $(NODE_COLORING_MENU).addClass("disabled"); $(NODE_COLORING_SIDEBAR_HEADER_LINK).attr("data-toggle", ""); }; const isNewWorkbook = (name) => { return grnState.nodeColoring.lastDataset === null || grnState.nodeColoring.lastDataset !== name; }; // Workbook Mode Functions const updateModeViews = () =>{ // Select correct dropdown item $(`${NETWORK_MODE_DROPDOWN} option`).removeAttr("selected"); $(`${NETWORK_MODE_DROPDOWN} option[value="${grnState.mode}"]`).prop("selected", true); // Select the correct menu items $(`${NETWORK_MODE_CLASS} option`).removeAttr("checked"); if (grnState.mode === NETWORK_GRN_MODE) { toggleLayout(NETWORK_MODE_GRN, NETWORK_MODE_PROTEIN_PHYS); } else if (grnState.mode === NETWORK_PPI_MODE) { toggleLayout(NETWORK_MODE_PROTEIN_PHYS, NETWORK_MODE_GRN); } }; const checkWorkbookModeSettings = () => { const hasExpression = hasExpressionData(grnState.workbook.expression); if (grnState.mode === NETWORK_PPI_MODE || !hasExpression) { grnState.nodeColoring.nodeColoringEnabled = false; grnState.nodeColoring.showMenu = true; grnState.colorOptimal = false; showNodeColoringMenus(); hideEdgeWeightOptions(); updateModeViews(); } else if (grnState.mode === NETWORK_GRN_MODE) { grnState.nodeColoring.nodeColoringEnabled = true; grnState.nodeColoring.showMenu = true; grnState.colorOptimal = true; showNodeColoringMenus(); showEdgeWeightOptions(); updateModeViews(); } }; $("body").on("click", () => { if (grnState.mode === NETWORK_PPI_MODE) { $(EXPORT_TO_UNWEIGHTED_GML_MENU).addClass("disabled"); } else if (grnState.mode === NETWORK_GRN_MODE) { $(EXPORT_TO_UNWEIGHTED_GML_MENU).removeClass("disabled"); } }); $(NETWORK_MODE_DROPDOWN).on("change", () => { grnState.mode = $(NETWORK_MODE_DROPDOWN).val(); checkWorkbookModeSettings(); refreshApp(); }); $(NETWORK_MODE_PROTEIN_PHYS).on("click", () => { grnState.mode = NETWORK_PPI_MODE; checkWorkbookModeSettings(); refreshApp(); }); $(NETWORK_MODE_GRN).on("click", () => { grnState.mode = NETWORK_GRN_MODE; checkWorkbookModeSettings(); refreshApp(); }); const shortenExpressionSheetName = (name) => { return (name.length > MAX_NUM_CHARACTERS_DROPDOWN) ? (name.slice(0, MAX_NUM_CHARACTERS_DROPDOWN) + "...") : name; }; const updateSpeciesMenu = () => { $(SPECIES_DISPLAY).val(grnState.genePageData.species); $(SPECIES_BUTTON_CRESS + " span").removeClass("glyphicon-ok"); $(SPECIES_BUTTON_FLY + " span").removeClass("glyphicon-ok"); $(SPECIES_BUTTON_HUMAN + " span").removeClass("glyphicon-ok"); $(SPECIES_BUTTON_YEAST + " span").removeClass("glyphicon-ok"); $(SPECIES_BUTTON_NEMATODE + " span").removeClass("glyphicon-ok"); $(SPECIES_BUTTON_MOUSE + " span").removeClass("glyphicon-ok"); if ($(SPECIES_DISPLAY).val() === "Arabidopsis_thaliana") { $(SPECIES_BUTTON_CRESS + " span").addClass("glyphicon-ok"); } if ($(SPECIES_DISPLAY).val() === "Drosophila_melanogaster") { $(SPECIES_BUTTON_FLY + " span").addClass("glyphicon-ok"); } if ($(SPECIES_DISPLAY).val() === "Caenorhabditis_elegans") { $(SPECIES_BUTTON_NEMATODE + " span").addClass("glyphicon-ok"); } if ($(SPECIES_DISPLAY).val() === "Homo_sapiens") { $(SPECIES_BUTTON_HUMAN + " span").addClass("glyphicon-ok"); } if ($(SPECIES_DISPLAY).val() === "Mus_musculus") { $(SPECIES_BUTTON_MOUSE + " span").addClass("glyphicon-ok"); } if ($(SPECIES_DISPLAY).val() === "Saccharomyces_cerevisiae") { $(SPECIES_BUTTON_YEAST + " span").addClass("glyphicon-ok"); } }; // helper method to check if the given data, a taxon id or a species name // is contained within the identified species, if it exists at all. export const identifySpeciesMenu = (data) => { var nameTax = grnState.nameToTaxon; for (var n in nameTax) { if (Object.values(nameTax[n]).includes(data.toString())) { grnState.genePageData.commonName = n; grnState.genePageData.species = nameTax[n].spec; grnState.genePageData.taxonJaspar = nameTax[n].jaspar; grnState.genePageData.taxonUniprot = nameTax[n].uniprot; grnState.genePageData.ensembl = nameTax[n].ensembl; grnState.genePageData.mine = nameTax[n].mine; $(SPECIES_DISPLAY).val(grnState.genePageData.species); updateSpeciesMenu(); return grnState.genePageData.identified; } } return false; }; const identifySpeciesOrTaxon = (data) => { var nameTax = grnState.nameToTaxon; for (var n in nameTax) { if (n === data) { // <-- change if to work grnState.genePageData.commonName = n; grnState.genePageData.species = nameTax[n].spec; grnState.genePageData.taxonJaspar = nameTax[n].jaspar.toString(); grnState.genePageData.taxonUniprot = nameTax[n].uniprot.toString(); grnState.genePageData.identified = true; grnState.genePageData.ensembl = nameTax[n].ensembl; grnState.genePageData.mine = nameTax[n].mine; $(SPECIES_DISPLAY).val(grnState.genePageData.species); updateSpeciesMenu(); return grnState.genePageData.identified; } for (var t in Object.values(nameTax[n])) { if (Object.values(nameTax[n])[t] === data) { grnState.genePageData.commonName = n; grnState.genePageData.species = nameTax[n].spec; grnState.genePageData.taxonJaspar = nameTax[n].jaspar.toString(); grnState.genePageData.taxonUniprot = nameTax[n].uniprot.toString(); grnState.genePageData.identified = true; grnState.genePageData.ensembl = nameTax[n].ensembl; grnState.genePageData.mine = nameTax[n].mine; $(SPECIES_DISPLAY).val(grnState.genePageData.species); updateSpeciesMenu(); return grnState.genePageData.identified; } } } return false; }; // renderNodeColoring: function () { }, // defined in graph.js const clearDropdownMenus = () => { $(TOP_DATASET_SELECTION_SIDEBAR).html(""); $(BOTTOM_DATASET_SELECTION_SIDEBAR).html(""); }; const resetDatasetDropdownMenus = (workbook) => { clearDropdownMenus(); $(".dataset-option").remove(); // clear all menu dataset options var createHTMLforDataset = function (name) { return ` <li class=\"dataset-option node-coloring-menu\" value=\"${name}\"> <a data-expression=\"${name}\"> <span class=\"glyphicon\"></span> &nbsp;${name} </a> </li>`; }; grnState.nodeColoring.nodeColoringOptions = []; for (var property in workbook.expression) { if (property.match(ENDS_IN_EXPRESSION_REGEXP)) { grnState.nodeColoring.nodeColoringOptions.push({value: property}); } } // Add expression database options grnState.database.expressionDatasets.forEach( option => grnState.nodeColoring.nodeColoringOptions.push({value: [option]})); $(BOTTOM_DATASET_SELECTION_SIDEBAR).append($("<option>") .attr("value", "Same as Top Dataset").text("Same as Top Dataset")); $(BOTTOM_DATASET_SELECTION_MENU).append(createHTMLforDataset("Same as Top Dataset")); // $(DATA_SET_SELECT).append($("<option>").attr("value", "Dahlquist").text("Dahlquist")); grnState.nodeColoring.nodeColoringOptions.forEach(function (option) { var shortenedSheetName = shortenExpressionSheetName(option.value); $(TOP_DATASET_SELECTION_SIDEBAR).append($("<option>") .addClass("dataset-option") .attr("value", option.value).text(shortenedSheetName)); $(TOP_DATASET_SELECTION_MENU) .append(createHTMLforDataset(option.value)); $(BOTTOM_DATASET_SELECTION_SIDEBAR).append($("<option>") .addClass("dataset-option") .attr("value", option.value).text(shortenedSheetName)); $(BOTTOM_DATASET_SELECTION_MENU) .append(createHTMLforDataset(option.value)); }); $("#topDatasetDropdownMenu li a span").first().addClass("glyphicon-ok"); $("#bottomDatasetDropdownMenu li a span").first().addClass("glyphicon-ok"); }; const updateLogFoldChangeMaxValue = () => { var value = logFoldChangeMaxValueInputValidation(grnState.nodeColoring.logFoldChangeMaxValue); $(LOG_FOLD_CHANGE_MAX_VALUE_SIDEBAR_INPUT).val(value); $(LOG_FOLD_CHANGE_MAX_VALUE_MENU).val(value); updaters.renderNodeColoring(); }; const removeAllChecksFromMenuDatasetOptions = (id) => { $(`${id} li a span`).each( function () { $(this).removeClass("glyphicon-ok"); } ); }; const updateTopDataset = () => { $(TOP_DATASET_SELECTION_SIDEBAR).val(grnState.nodeColoring.topDataset); removeAllChecksFromMenuDatasetOptions(TOP_DATASET_SELECTION_MENU); $(`${TOP_DATASET_SELECTION_MENU} li[value='${grnState.nodeColoring.topDataset}'] a span`).addClass("glyphicon-ok"); updaters.renderNodeColoring(); }; const updateBottomDataset = () => { if (grnState.nodeColoring.bottomDataSameAsTop) { $(BOTTOM_DATASET_SELECTION_SIDEBAR).val("Same as Top Dataset"); removeAllChecksFromMenuDatasetOptions(BOTTOM_DATASET_SELECTION_MENU); $(`${BOTTOM_DATASET_SELECTION_MENU} li[value='${"Same as Top Dataset"}'] a span`).addClass("glyphicon-ok"); } else { $(BOTTOM_DATASET_SELECTION_SIDEBAR).val(grnState.nodeColoring.bottomDataset); removeAllChecksFromMenuDatasetOptions(BOTTOM_DATASET_SELECTION_MENU); /* eslint-disable max-len */ $(`${BOTTOM_DATASET_SELECTION_MENU} li[value='${grnState.nodeColoring.bottomDataset}'] a span`) .addClass("glyphicon-ok"); /* eslint-enable max-len */ } updaters.renderNodeColoring(); }; if (!grnState.genePageData.identified) { $(SPECIES_DISPLAY).val(grnState.genePageData.species); } export const updateApp = grnState => { if (grnState.newWorkbook) { checkWorkbookModeSettings(); grnState.normalizationMax = max(grnState.workbook.positiveWeights.concat(grnState.workbook.negativeWeights)); displayworkbook(grnState.workbook, grnState.name); expandLayoutSidebar(); clearDropdownMenus(); // check if the species has been identified yet, if not try to identify it // also checks if the areas have been populated at all var workbookSpecies = grnState.workbook.meta.species; var workbookTaxon = grnState.workbook.meta.taxon_id; if (identifySpeciesOrTaxon(workbookSpecies) || identifySpeciesOrTaxon(workbookTaxon)) { identifySpeciesOrTaxon(workbookSpecies); identifySpeciesOrTaxon(workbookTaxon); } // nodeColoringEnabled will only be set the very first time; because otherwise the user will have // made a choice and we will let the choice stick. if (hasExpressionData(grnState.workbook.expression)) { resetDatasetDropdownMenus(grnState.workbook); if (grnState.nodeColoring.nodeColoringEnabled === undefined) { grnState.nodeColoring.nodeColoringEnabled = true; } if (isNewWorkbook(name)) { grnState.nodeColoring.showMenu = true; grnState.nodeColoring.lastDataset = name; showNodeColoringMenus(); } grnState.nodeColoring.topDataset = $(TOP_DATASET_SELECTION_SIDEBAR).find(":selected").attr("value"); if ($(BOTTOM_DATASET_SELECTION_SIDEBAR).find(":selected").attr("value") === "Same as Top Dataset") { grnState.nodeColoring.bottomDataset = grnState.nodeColoring.topDataset; grnState.nodeColoring.bottomDataSameAsTop = true; } else { grnState.nodeColoring.bottomDataset = $(BOTTOM_DATASET_SELECTION_SIDEBAR).find(":selected").attr("value"); grnState.nodeColoring.bottomDataSameAsTop = false; } } else { if (grnState.nodeColoring.nodeColoringEnabled === undefined) { grnState.nodeColoringEnabled = false; } } refreshApp(); // Rare exception to the MVC cycle: right now we have no way of knowing whether the workbook has changed // (which is what necessitates displayworkbook), so we mark the model here. grnState.newWorkbook = false; } synchronizeNormalizationValues(grnState.normalizationMax); synchronizeGrayEdgeValues(grnState.grayEdgeThreshold); // Dashed Line Synchronization if (grnState.dashedLine) { $(GREY_EDGES_DASHED_MENU + " span").addClass("glyphicon-ok"); $(GREY_EDGES_DASHED_MENU).prop("checked", "checked"); $(GREY_EDGES_DASHED_SIDEBAR).prop("checked", "checked"); } else { $(GREY_EDGES_DASHED_MENU + " span").removeClass("glyphicon-ok"); $(GREY_EDGES_DASHED_MENU).removeProp("checked"); $(GREY_EDGES_DASHED_SIDEBAR).removeProp("checked"); } // Weights functions if (grnState.edgeWeightDisplayOption === SHOW_WEIGHTS_MOUSEOVER) { synchronizeShowWeightsMouseover(); } else if (grnState.edgeWeightDisplayOption === SHOW_ALL_WEIGHTS) { synchronizeShowAllWeights(); } else if (grnState.edgeWeightDisplayOption === HIDE_ALL_WEIGHTS) { synchronizeHideAllWeights(); } // Enable/Disable Colored edges $(COLOR_EDGES_SIDEBAR).prop("checked", grnState.colorOptimal); const classFunction = `${grnState.colorOptimal ? "add" : "remove"}Class`; $(COLOR_EDGES_MENU)[classFunction](ACTIVE_COLOR_OPTION); $(`${COLOR_EDGES_MENU}>span`)[classFunction]("glyphicon-ok"); // Graph Layout if (grnState.graphLayout === FORCE_GRAPH) { updatetoForceGraph(); } else if (grnState.graphLayout === GRID_LAYOUT) { updatetoGridLayout(); } // Viewport updateViewportSize(grnState.viewportSize); // Node Coloring if (grnState.workbook !== null && grnState.nodeColoring.nodeColoringEnabled && hasExpressionData(grnState.workbook.expression)) { grnState.nodeColoring.showMenu = true; $(AVG_REPLICATE_VALS_TOP_SIDEBAR).prop("checked", true); $(AVG_REPLICATE_VALS_BOTTOM_SIDEBAR).prop("checked", true); $(`${NODE_COLORING_TOGGLE_MENU} span`).addClass("glyphicon-ok"); $(NODE_COLORING_TOGGLE_SIDEBAR).prop("checked", true); $(LOG_FOLD_CHANGE_MAX_VALUE_CLASS).val(DEFAULT_MAX_LOG_FOLD_CHANGE); $(NODE_COLORING_SIDEBAR_BODY).removeClass("hidden"); $(NODE_COLORING_MENU).removeClass("hidden"); $(NODE_COLORING_NAVBAR_OPTIONS).removeClass("hidden"); if (grnState.mode === NETWORK_PPI_MODE) { displayPPINodeColorWarning(grnState.ppiNodeColorWarningDisplayed); grnState.ppiNodeColorWarningDisplayed = true; } if (grnState.database.expressionDatasets.includes(grnState.nodeColoring.topDataset) && grnState.workbook.expression[grnState.nodeColoring.topDataset] === undefined) { if ($(NODE_COLORING_TOGGLE_SIDEBAR).prop("checked")) { loadExpressionDatabase(true); } } else if (grnState.database.expressionDatasets.includes(grnState.nodeColoring.bottomDataset) && !grnState.nodeColoring.bottomDataSameAsTop && grnState.workbook.expression[grnState.nodeColoring.bottomDataset] === undefined) { if (!grnState.nodeColoring.bottomDataSameAsTop) { loadExpressionDatabase(false); } } else { updaters.renderNodeColoring(); } } else if (grnState.workbook !== null && !hasExpressionData(grnState.workbook.expression) && grnState.nodeColoring.nodeColoringEnabled) { if ((grnState.workbook.expression[grnState.nodeColoring.topDataset] === undefined) || (!grnState.nodeColoring.bottomDataSameAsTop && grnState.workbook.expression[grnState.nodeColoring.bottomDataset] === undefined)) { updaters.removeNodeColoring(); resetDatasetDropdownMenus(grnState.workbook); } grnState.nodeColoring.showMenu = true; grnState.nodeColoring.topDataset = grnState.nodeColoring.topDataset ? grnState.nodeColoring.topDataset : "Dahlquist_2018_wt"; grnState.nodeColoring.bottomDataset = grnState.nodeColoring.bottomDataset ? grnState.nodeColoring.bottomDataset : "Dahlquist_2018_wt"; $(NODE_COLORING_TOGGLE_SIDEBAR).prop("checked", true); $(`${NODE_COLORING_TOGGLE_MENU} span`).addClass("glyphicon-ok"); $(NODE_COLORING_SIDEBAR_BODY).removeClass("hidden"); $(NODE_COLORING_MENU).removeClass("hidden"); $(NODE_COLORING_NAVBAR_OPTIONS).removeClass("hidden"); $(LOG_FOLD_CHANGE_MAX_VALUE_CLASS).val(DEFAULT_MAX_LOG_FOLD_CHANGE); $(LOG_FOLD_CHANGE_MAX_VALUE_CLASS).addClass("hidden"); $(LOG_FOLD_CHANGE_MAX_VALUE_SIDEBAR_BUTTON).addClass("hidden"); $(LOG_FOLD_CHANGE_MAX_VALUE_HEADER).addClass("hidden"); if ($(NODE_COLORING_TOGGLE_SIDEBAR).prop("checked")) { if (grnState.workbook.expression[grnState.nodeColoring.topDataset] === undefined) { loadExpressionDatabase(true); } else if (!grnState.nodeColoring.bottomDataSameAsTop && grnState.workbook.expression[grnState.nodeColoring.bottomDataset] === undefined) { loadExpressionDatabase(false); } else { enableNodeColoringUI(); // There is as problem here! When a dataset from the database is used to do node coloring, // but then the layout of the graph is changed (force graph to grid layout, for instance), // node coloring goes away, seemingly inexplicably. // !!!!! TEMPORARY WORKAROUND: // Calling `updaters.renderNodeColoring()` inline does not succeed; instead, a delay // has to take place, done here via `setTimeout`. // // The delay is built-in to the cases where a query has to happen first. // // For some reason, calling updates.renderNodeColoring() _synchronously_ does not // actually perform the node coloring. // // Investigate why a timeout is required in order for node coloring to take place // successfully in this case. setTimeout(() => updaters.renderNodeColoring(), 250); } if (grnState.mode === NETWORK_PPI_MODE) { displayPPINodeColorWarning(grnState.ppiNodeColorWarningDisplayed); grnState.ppiNodeColorWarningDisplayed = true; } } } else if (grnState.workbook !== null && !grnState.nodeColoring.nodeColoringEnabled) { $(NODE_COLORING_SIDEBAR_BODY).addClass("hidden"); $(NODE_COLORING_MENU).addClass("disabled"); $(NODE_COLORING_NAVBAR_OPTIONS).addClass("hidden"); $(`${NODE_COLORING_TOGGLE_MENU} span`).removeClass("glyphicon-ok"); $(NODE_COLORING_TOGGLE_SIDEBAR).prop("checked", false); if (grnState.mode === NETWORK_PPI_MODE) { grnState.ppiNodeColorWarningDisplayed = false; } } if (grnState.workbook !== null && grnState.workbook.sheetType === "weighted") { showEdgeWeightOptions(); } else if (grnState.workbook !== null && grnState.workbook.sheetType === "unweighted") { hideEdgeWeightOptions(); } else { hideEdgeWeightOptions(); } if (grnState.nodeColoring.averageTopDataset) { $(AVG_REPLICATE_VALS_TOP_MENU + " span").addClass("glyphicon-ok"); $(AVG_REPLICATE_VALS_TOP_MENU).prop("checked", "checked"); $(AVG_REPLICATE_VALS_TOP_SIDEBAR).prop("checked", "checked"); updaters.renderNodeColoring(); } else { $(AVG_REPLICATE_VALS_TOP_MENU + " span").removeClass("glyphicon-ok"); $(AVG_REPLICATE_VALS_TOP_MENU).removeProp("checked"); $(AVG_REPLICATE_VALS_TOP_SIDEBAR).removeProp("checked"); updaters.renderNodeColoring(); } if (grnState.nodeColoring.averageBottomDataset) { $(AVG_REPLICATE_VALS_BOTTOM_MENU + " span").addClass("glyphicon-ok"); $(AVG_REPLICATE_VALS_BOTTOM_MENU).prop("checked", "checked"); $(AVG_REPLICATE_VALS_BOTTOM_SIDEBAR).prop("checked", "checked"); updaters.renderNodeColoring(); } else { $(AVG_REPLICATE_VALS_BOTTOM_MENU + " span").removeClass("glyphicon-ok"); $(AVG_REPLICATE_VALS_BOTTOM_MENU).removeProp("checked"); $(AVG_REPLICATE_VALS_BOTTOM_SIDEBAR).removeProp("checked"); updaters.renderNodeColoring(); } if (grnState.nodeColoring.showMenu) { showNodeColoringMenus(); } else { disableNodeColoringMenus(); } updateLogFoldChangeMaxValue(); updateTopDataset(); updateBottomDataset(); updateSliderState(grnState.slidersLocked); if (grnState.showUndoReset) { $(UNDO_SLIDERS_RESET_SIDEBAR).prop("disabled", false); $(UNDO_SLIDERS_RESET_MENU).parent().removeClass("disabled"); } else { $(UNDO_SLIDERS_RESET_SIDEBAR).prop("disabled", true); $(UNDO_SLIDERS_RESET_MENU).parent().addClass("disabled"); } updateChargeSliderValues(); updateLinkDistanceSliderValues(); $(ZOOM_CONTROL).prop({ disabled: !grnState.workbook }); if (!grnState.workbook) { // Set initial values when there is no workbook: this is necessarily explicit because Firefox // preserves these values even upon a browser reload. $(ZOOM_INPUT).val(ZOOM_DISPLAY_MIDDLE); $(ZOOM_SLIDER).val(ZOOM_ADAPTIVE_MAX_SCALE); } refreshApp(); }; export { stopLoadingIcon, startLoadingIcon, adjustGeneNameForExpression};