/**
* @file tmapp.js Main base for TissUUmaps to work
* @author Leslie Solorzano
* @see {@link tmapp}
*/
/**
* @namespace tmapp
* @version tmapp 2.0
* @classdesc The root namespace for tmapp.
*/
tmapp = {
_url_suffix: "",
_scrollDelay: 900,
fixed_file: "",
slideFilename:"Main"
}
/**
* Get all the buttons from the interface and assign all the functions associated to them */
tmapp.registerActions = function () {
tmapp["object_prefix"] = tmapp.options_osd.id.split("_")[0];
var op = tmapp["object_prefix"];
interfaceUtils.listen(op + '_collapse_btn','click', function () { interfaceUtils.toggleRightPanel() },false);
interfaceUtils.listen(op + '_drawregions_btn','click', function () { regionUtils.regionsOnOff() },false);
interfaceUtils.listen(op + '_export_regions','click', function () { regionUtils.exportRegionsToJSON() },false);
interfaceUtils.listen(op + '_import_regions','click', function () { regionUtils.importRegionsFromJSON() },false);
interfaceUtils.listen(op + '_export_regions_csv','click', function () { regionUtils.pointsInRegionsToCSV() },false);
interfaceUtils.listen(op + '_fillregions_btn','click', function () { regionUtils.fillAllRegions(); },false);
interfaceUtils.listen("capture_viewport","click",function(){overlayUtils.savePNG()},false)
interfaceUtils.listen("plus-1-button","click",function(){interfaceUtils.generateDataTabUI()},false)
interfaceUtils.listen('save_project_menu', 'click', function() { projectUtils.saveProject() }, false);
interfaceUtils.listen('load_project_menu', 'click', function() { projectUtils.loadProjectFile() }, false);
document.addEventListener("mousedown",function(){tmapp["ISS_viewer"].removeOverlay("ISS_marker_info");});
// dataUtils.processEventForCSV("morphology",cpop + '_csv');
//dataUtils.processEventForCSV("gene",op + '_csv');
var navtabs=document.getElementsByClassName("nav-tabs")[0];
var uls=navtabs.getElementsByTagName("ul");
for(var i=0;i<uls.length;i++){
var as=uls[i].getElementsByTagName("a");
for(var j=0;j<as.length;j++){
as[j].addEventListener("click",function(){interfaceUtils.hideTabsExcept($(this))});
}
}
}
/**
* This method is called when the document is loaded. The tmapp object is built as an "app" and init is its main function.
* Creates the OpenSeadragon (OSD) viewer and adds the handlers for interaction.
* To know which data one is referring to, there are Object Prefixes (op). For In situ sequencing projects it can be "ISS" for
* Cell Profiler data it can be "CP".
* If there are images to be displayed on top of the main image, they are stored in the layers object and, if there are layers
* it will create the buttons to display them in the settings panel.
* The SVG overlays for the viewer are also initialized here
* @summary After setting up the tmapp object, initialize it*/
tmapp.init = function () {
//This prefix will be called by all other utilities in js/utils
tmapp["object_prefix"] = tmapp.options_osd.id.split("_")[0];
var op = tmapp["object_prefix"];
var vname = op + "_viewer";
//init OSD viewer
tmapp[vname] = OpenSeadragon(tmapp.options_osd);
// Disable keyboard hack
tmapp[vname].innerTracker.keyHandler = null;
tmapp[vname].innerTracker.keyDownHandler = null;
tmapp[vname].innerTracker.keyPressHandler = null;
if(!tmapp.layers){
tmapp.layers = [];
}
overlayUtils.addAllLayers();
//Create svgOverlay(); so that anything like D3, or any canvas library can act upon. https://d3js.org/
var svgovname = tmapp["object_prefix"] + "_svgov";
tmapp[svgovname] = tmapp[vname].svgOverlay();
//main node
overlayUtils._d3nodes[op + "_svgnode"] = d3.select(tmapp[svgovname].node());
//overlay for marker data //main node
overlayUtils._d3nodes[op + "_markers_svgnode"] = overlayUtils._d3nodes[op + "_svgnode"].append("g")
.attr("id", op + "_markers_svgnode");
//overlay for region data //main node
overlayUtils._d3nodes[op + "_regions_svgnode"] = overlayUtils._d3nodes[op + "_svgnode"].append("g")
.attr("id", op + "_regions_svgnode");
//overlay for CP data
var cpop="CP"; //main node;
overlayUtils._d3nodes[cpop+"_svgnode"] = overlayUtils._d3nodes[op + "_svgnode"].append("g")
.attr("id", cpop+"_svgnode");
var click_handler = function (event) {
if (event.quick) {
if (overlayUtils._drawRegions) {
//call region creator and drawer
regionUtils.manager(event);
}
} else { //if it is not quick then its panning
//scroll_handler();
}
};
//OSD handlers are not registered manually they have to be registered
//using MouseTracker OSD objects
/*var ISS_mouse_tracker = new OpenSeadragon.MouseTracker({
element: tmapp[vname].canvas,
clickHandler: click_handler
}).setTracking(true);*/
tmapp["ISS_viewer"].addHandler('canvas-click', click_handler);
tmapp["ISS_viewer"].addHandler("animation-finish", function animationFinishHandler(event){
d3.selectAll("." + regionUtils._drawingclass).selectAll('polyline').each(function(el) {
$(this).attr('stroke-width', regionUtils._polygonStrokeWidth / tmapp["ISS_viewer"].viewport.getZoom());
});
d3.selectAll("." + regionUtils._drawingclass).selectAll('circle').each(function(el) {
$(this).attr('r', 10* regionUtils._handleRadius / tmapp["ISS_viewer"].viewport.getZoom());
});
d3.selectAll(".regionpoly").each(function(el) {
$(this).attr('stroke-width', regionUtils._polygonStrokeWidth / tmapp["ISS_viewer"].viewport.getZoom());
});
var op = tmapp["object_prefix"];
if (tmapp[op + "_viewer"].world.getItemAt(0).viewportToImageZoom(tmapp[op + "_viewer"].viewport.getZoom()) > 0.05) {
var count = tmapp[op + "_viewer"].world.getItemCount();
for (var i = 0; i < count; i++) {
var tiledImage = tmapp[op + "_viewer"].world.getItemAt(i);
tiledImage.immediateRender = true;
}
tmapp[op + "_viewer"].imageLoaderLimit = 50;
}
});
tmapp["ISS_viewer"].addHandler("animation-start", function animationFinishHandler(event){
var op = tmapp["object_prefix"];
var count = tmapp[op + "_viewer"].world.getItemCount();
for (var i = 0; i < count; i++) {
var tiledImage = tmapp[op + "_viewer"].world.getItemAt(i);
tiledImage.immediateRender = false;
}
tmapp[op + "_viewer"].imageLoaderLimit = 1;
});
elt = document.getElementById("ISS_globalmarkersize");
if (elt) {
tmapp[vname].addControl(elt,{
anchor: OpenSeadragon.ControlAnchor.TOP_RIGHT
});
elt.classList.add("d-none");
}
filterUtils.initFilters();
if (window.hasOwnProperty("glUtils")) {
console.log("Using GPU-based marker drawing (WebGL canvas)")
glUtils.init();
} else {
console.log("Using CPU-based marker drawing (SVG canvas)")
}
if (dataUtils._hdf5Api === undefined) {
dataUtils._hdf5Api = new H5AD_API()
}
} //finish init
/**
* Options for the fixed and moving OSD
* all options are described here https://openseadragon.github.io/docs/OpenSeadragon.html#.Options */
tmapp.options_osd = {
id: "ISS_viewer",
prefixUrl: "js/openseadragon/images/",
navigatorSizeRatio: 0.15,
wrapHorizontal: false,
showNavigator: true,
navigatorPosition: "BOTTOM_LEFT",
animationTime: 0.0,
blendTime: 0,
minZoomImageRatio: 1,
maxZoomPixelRatio: 30,
immediateRender: false,
zoomPerClick: 1.0,
constrainDuringPan: true,
visibilityRatio: 0.85,
showNavigationControl: false,
maxImageCacheCount:2000,
imageSmoothingEnabled:false,
preserveImageSizeOnResize: true,
imageLoaderLimit: 50,
gestureSettingsUnknown: {
flickEnabled: false
},
gestureSettingsTouch: {
flickEnabled: false
},
gestureSettingsPen: {
flickEnabled: false
}
}
function toggleFullscreen() {
let full_ui = document.getElementById("main-ui");
let bIsFullscreen = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen;
if (!bIsFullscreen) {
if (full_ui.requestFullscreen) {
full_ui.requestFullscreen();
} else if (full_ui.webkitRequestFullscreen) {
full_ui.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
} else if (full_ui.msRequestFullscreen) {
full_ui.msRequestFullscreen();
} else if (full_ui.webkitRequestFullscreen) {
full_ui.mozRequestFullscreen();
}
} else {
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.msCancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen()
}
}
}
function toggleNavbar(turn_on = null) {
let main_navbar = document.getElementsByTagName("nav")[0];
if (turn_on === true) {
main_navbar.classList.remove("d-none");
} else if (turn_on === false) {
main_navbar.classList.add("d-none");
} else if (turn_on === null) {
if (main_navbar.classList.contains("d-none")) {
toggleNavbar(true);
} else {
toggleNavbar(false);
}
}
}
$( document ).ready(function() {
let ISS_viewer = document.getElementById("ISS_viewer");
let ISS_viewer_container = document.getElementById("ISS_viewer_container");
ISS_viewer.addEventListener('dblclick', function (e) {
// Open in fullscreen if double clicked
toggleFullscreen();
});
let full_ui = document.getElementById("main-ui");
full_ui.addEventListener('fullscreenchange', (event) => {
// document.fullscreenElement will point to the element that
// is in fullscreen mode if there is one. If not, the value
// of the property is null.
if (document.fullscreenElement) {
toggleNavbar(false);
} else {
toggleNavbar(true);
}
});
ISS_viewer_container.addEventListener("keydown", (event) => {
if (event.key === "0") {
interfaceUtils.toggleRightPanel();
} else if (event.key === "f") {
toggleFullscreen();
} else if (event.key === "m") {
for (const [key, value] of Object.entries(dataUtils.data)) {
$("#"+key+"_all_check").click();
$("#"+key+"_All_check").click();
}
} else if (event.key === "r") {
$("#ISS_fillregions_btn").click();
}
});
});