UNPKG

@galaxyproject/nora

Version:

NORA Medical Imaging Viewer

1,386 lines (1,136 loc) 426 kB
// ====================================================================================== // ====================================================================================== // ============= KMedViewer // ====================================================================================== // ====================================================================================== function KMedViewer(viewport, master) { /** @class * @alias KMedViewer */ var that = KPrototypeViewer(viewport, master); that.viewerType = 'medViewer'; that.type = 'mainview'; var $container = that.$container; var $topRow = that.$topRow; var toolbar = that.toolbar; toolbar.$info.hide(); var $canvascontainer = $("<div class='KViewPort_canvascontainer'></div>").appendTo($container); that.$canvascontainer = $canvascontainer; // attach the histogram that.histoManagercnt = 0; var histoManager = createHistoManager(that); /** @type {KHistoManager} */ that.transfactor = 1; that.histoManager = histoManager; histoManager.blending = undefined; histoManager.posnegsym = undefined; histoManager.blocky = undefined; histoManager.onclimchange = function(ev) { sliceDrawUpdateNeeded = true; histoManager.clim_manually_modified = true; signalhandler.send("climChange", { id: that.currentFileID, val: histoManager.clim, ev: ev }); } var infomenu = function(_that) { return KContextMenu(function() { var nii = that.nii; var msz; if (nii.sizes.length > 3) msz = "matrix: " + nii.sizes[0].toFixed(0) + '&nbsp;&nbsp;' + nii.sizes[1].toFixed(0) + '&nbsp;&nbsp;' + nii.sizes[2].toFixed(0) + '&nbsp;&nbsp;' + nii.sizes[3].toFixed(0); else msz = "matrix: " + nii.sizes[0].toFixed(0) + '&nbsp;&nbsp;' + nii.sizes[1].toFixed(0) + '&nbsp;&nbsp;' + nii.sizes[2].toFixed(0); if (nii.currentTimePoint.t != 0) msz += " (t:" + (nii.currentTimePoint.t + 1) + ")"; if (that.currentFileinfo) var psid = that.currentFileinfo.patients_id + " " + that.currentFileinfo.studies_id; else var psid = "localfile"; msz = that.currentFilename + " <br> ID: " + psid + "<br>" + msz + "<br>voxsize: " + nii.voxSize[0].toFixed(1) + '&nbsp;&nbsp;' + nii.voxSize[1].toFixed(1) + '&nbsp;&nbsp;' + nii.voxSize[2].toFixed(1) return $("<ul class='menu_context'>").append($("<li >" + msz + " </li>")); }, function(str, ev) {}) }(that); that.switchToMosaic = function() { if (gl_enabled) toggle3D(); that.mosaicview.active = true; setCanvasLayout(); drawSlice(); } that.switchToSingle= function() { if (gl_enabled) toggle3D(); if (that.mosaicview.active) that.mosaicview.active = false; setCanvasLayout(); if (!that.mosaicview.active) drawSlice(); } that.switchTo3D = function(callback) { if (that.mosaicview.active) that.mosaicview.active = false; if (!gl_enabled) toggle3D(undefined,callback); else { setCanvasLayout(); drawSlice(); } } that.viewContextMenu = new KContextMenu( function() { var $menu = $("<ul class='menu_context'>"); var name = ['Saggital', 'Coronal', 'Transversal']; $menu.append($("<hr width='100%'> ")); $menu.append($("<span> &nbsp View</span>")); $menu.append($("<hr width='100%'> ")); var sel = (!gl_enabled && !that.mosaicview.active) ? 'check-' : ''; $menu.append($("<li onchoice='single' > <i onchoice='single' class='fa fa-" + sel + "circle-o'></i><i class='leftaligned fa fa-user'></i> Single slice </li>")); var sel = that.mosaicview.active ? 'check-' : ''; $menu.append($("<li onchoice='mosaic' > <i onchoice='mosaic' class='fa fa-" + sel + "circle-o'></i> <i class='leftaligned fa fa-th'></i> Mosaic </li>")); var sel = gl_enabled ? 'check-' : ''; if (typeof KMedImg3D != "undefined") $menu.append($("<li onchoice='3dview' > <i onchoice='3dview' class='fa fa-" + sel + "circle-o'></i> <i class='leftaligned fa fa-cube'></i> 3D view </li>")); // $menu.append($("<li onchoice='curveview' > <i onchoice='curveview' class='fa fa-" + sel + "circle-o'></i> <i class='leftaligned fa fa-line-chart'></i> Curve view </li>")); $menu.append($("<hr width='100%'> ")); var sel = worldLockedToMaster ? 'check-' : ''; $menu.append($("<li onchoice='lock' > Global coordinates<i onchoice='lock' class='fa fa-" + sel + "square-o'></i> </li>")); var permstr = "<li onchoice='...' >Permutation<i onchoice='lock' class='fa fa-caret-right'></i> <ul>" ; for (var k = 0; k < presetForm_viewer_permorder.choices.length;k++ ) { var sel = (that.nii.reordering == presetForm_viewer_permorder.ids[k]) ? 'check-' : ''; permstr += " <li onchoice='permorder_"+presetForm_viewer_permorder.ids[k]+"' >"+ presetForm_viewer_permorder.choices[k] + "<i onchoice='lock' class='fa fa-"+sel+"square-o'></i> </li> " } permstr += "</ul></li>"; $menu.append($(permstr)); if (!gl_enabled) { $menu.append($("<hr width='100%'> ")); $menu.append($("<span> &nbsp Slicing</span>")); $menu.append($("<hr width='100%'> ")); var perm = [0, 1, 2]; //[viewer.nii.permutationOrder[0],viewer.nii.permutationOrder[1],viewer.nii.permutationOrder[2]]; perm[-1] = -1; for (var k = 0; k < 3; k++) { var sel = ''; // if (slicingDimOfWorld == that.nii.permutationOrder[k]) // sel = 'check-'; if (slicingDimOfWorld == k) sel = 'check-'; $menu.append($("<li onchoice='vis_" + k + "' > " + name[k] + " <i onchoice='vis_" + k + "' class='fa fa-" + sel + "circle-o'></i> </li>")); } } return $menu; } ,function(str, ev) { if (str != undefined) { if (str.search("vis") != -1) { setSlicingDimOfWorld(parseInt(str.substring(4))); } else if (str == "single") { that.switchToSingle(); } else if (str == "mosaic") { that.switchToMosaic(); } else if (str == "3dview") { that.switchTo3D(); } else if (str == "curveview") { if (that.mosaicview.active) that.mosaicview.active = false; if (gl_enabled) toggle3D(); KMedImgCurve( that ); } else if (str == 'lock') { changeWorldLock(); // if (worldLockedToMaster) // customPoint = math.matrix(getWorldPosition()); // worldLockedToMaster = !worldLockedToMaster; // drawSlice({ // mosaicdraw: true // }); } else if (str.substring(0,10) == 'permorder_') { var id = str.substring(10); that.niiOriginal.applyReordering(id); signalhandler.send("updateImage",{id:that.currentFileID}); } } } ,undefined,false); function KIcon(name,$div,style) { if (style == undefined) style = ""; var $icon; if (name == "planecube") { style = style = style +"stroke:lightgray;stroke-width:1"; $icon = []; $icon[2] = $("<div> <svg style='' height=12 width=12>"+ " <polygon points='1,3 1,9 6,11 6,5' style='fill:none;"+style+"' />"+ " <polygon points='11,3 11,9 6,11 6,5' style='fill:none;"+style+"' />"+ " <polygon points='1,3 6,5 11,3 6,1' style='fill:yellow;"+style+"' />"+ +"</svg> </div>"); $icon[1] = $("<div> <svg style='' height=12 width=12>"+ " <polygon points='1,3 1,9 6,11 6,5' style='fill:none;"+style+"' />"+ " <polygon points='11,3 11,9 6,11 6,5' style='fill:yellow;"+style+"' />"+ " <polygon points='1,3 6,5 11,3 6,1' style='fill:none;"+style+"' />"+ +"</svg> </div>"); $icon[0] = $("<div> <svg style='' height=12 width=12>"+ " <polygon points='1,3 1,9 6,11 6,5' style='fill:yellow;"+style+"' />"+ " <polygon points='11,3 11,9 6,11 6,5' style='fill:none;"+style+"' />"+ " <polygon points='1,3 6,5 11,3 6,1' style='fill:none;"+style+"' />"+ +"</svg> </div>"); } $div.append($icon); return $icon; } toolbar.$cmapReset = $("<div class='KViewPort_tool KViewPort_tool_cmapReset'><i class='fa fa-reply fa-1x'></i></div>").click(function() { resetColorMapLims(); }).appendTooltip("resetclims") toolbar.$cmap = $("<div class='KViewPort_tool KViewPort_tool_cmap'><i class='fa fa-empty fa-1x'>&nbsp&nbsp&nbsp&nbsp</i></div>").click(histoManager.cmapSelectorMenu).appendTooltip("changecolormap") toolbar.$quiver = $("<div class='KViewPort_tool'> <i class='fa fa-code-fork fa-1x'> </div>").click(function(e) { quiver.menu(e,that) }).appendTooltip("quiverprops") that.quiverdiv = toolbar.$quiver toolbar.$info = $("<div class='KViewPort_tool'> <i class='fa fa-info-circle fa-1x'> </div>").click(infomenu); toolbar.$lock = $("<div class='KViewPort_tool'> <i class='fa fa-lock fa-1x'> </div>").click(changeWorldLock); toolbar.$view = $("<div class='KViewPort_tool'> <i class='fa fa-photo fa-1x'> </div>").click(that.viewContextMenu); toolbar.$createIso = $("<div class='KViewPort_tool'> <i class='fa fa-play fa-1x'> </div>"); toolbar.$toggle3D = $("<div class='KViewPort_tool KViewPort_tool_toggle3D'><i class='fa fa-1x'><span>3D</span></i></div>").click(function() { toggle3D() }).appendTooltip("switchto3d"); toolbar.$slicingDim = $("<div class='KViewPort_tool KViewPort_tool_slicingDim'></div>").click(toggleSlicingDim).appendTooltip("changeslicing") toolbar.$sliceCubes = KIcon('planecube',toolbar.$slicingDim); toolbar.attach(toolbar.$cmapReset).attach(toolbar.$cmap).attach(toolbar.$info).attach(toolbar.$quiver).attach(toolbar.$toggle3D).attach(toolbar.$lock).attach(toolbar.$view).attach(toolbar.$slicingDim); var layoutbar = that.layoutbar; layoutbar.$slicing = $("<div class='KViewPort_tool_layout'><i class='fa fa-1x'></i></div>").click(toggleSlicingDim).appendTooltip("changeslicing") if (typeof KMedImg3D != "undefined") { layoutbar.$shortcut3d = $("<span class='KViewPort_tool_layout layout3dshortcut'> 3D</span>"); layoutbar.$shortcut3d.click(function() { toggle3D(); }); } layoutbar.$sliceCubes = KIcon('planecube',layoutbar.$slicing); layoutbar.$center = $("<div class='KViewPort_tool_layout'><i class='fa fa-dot-circle-o fa-1x'></i></div>").click( function() { signalhandler.send("centralize"); } ).appendTooltip("centerview"); layoutbar.attach(layoutbar.$slicing); if (typeof KMedImg3D != "undefined") layoutbar.attach(layoutbar.$shortcut3d); // ******** slide slices and slide zoom layoutbar.$slideslices = $("<span class='KViewPort_tool_layout'> <i class='fa fa-unsorted fa-1x'></i> </span>"); layoutbar.$slidezoom = $("<span class='KViewPort_tool_layout'> <i class='fa fa-search fa-1x'></i> </span>"); // slice slider attachMouseSlider(layoutbar.$slideslices, { mousedown: function(){ return { startval: currentSlice, startval_percent: currentSlice / (that.nii.sizes[slicingDimOfArray]-1) } } , mousemove:function(ev,dx,dy,mousedownvar) { return that.setSlicePos(slicingDimOfArray, mousedownvar.startval - that.nii.arrayReadDirection[slicingDimOfArray]*dy*(that.nii.sizes[slicingDimOfArray]-1) ) }, mouseup: function(){ } }); // zoom slider attachMouseSlider(layoutbar.$slidezoom, { mousedown: function() { return { startzoomFac: that.zoomFac, startMosaicZoom: that.mosaicview.zoom} }, mousemove:function(ev,dx,dy,mousedownvar, lastdx, lastdy) { if (gl_enabled) { var zoominc = 1 - lastdy*0.004; var maxex = that.computeMaxExtentFac() that.gl.camera.inertialRadiusOffset -= maxex * (1 - zoominc); if (isNaN(that.gl.camera.inertialRadiusOffset)) that.gl.camera.inertialRadiusOffset = 1; that.gl.sync3DViews(that.gl.camera.inertialAlphaOffset,that.gl.camera.inertialBetaOffset, that.gl.camera.inertialPanningX,that.gl.camera.inertialPanningY,that.gl.camera.inertialRadiusOffset ); that.gl.activateRenderLoop(); setTimeout(that.gl.setQuality,350); } else if (that.mosaicview.active) { that.mosaicview.zoom = mousedownvar.startMosaicZoom + dy*10; if (that.mosaicview.zoom > 1) that.mosaicview.zoom = 1; if (KViewer.mainViewport != -1) signalhandler.send("mosaic_changelayout",that.mosaicview); else { setCanvasLayout(); drawHairCross(); } } else { var zoominc = 1 - lastdy*0.01; $(".markerpoint,.markerruler").css('display','none') if (worldLockedToMaster & master.globalCoordinates) { signalhandler.send("setZoom", zoominc ); signalhandler.send("positionChange", {nosliceupdate:true},that.positionChanger); // why this ...markers? } else { setZoom(zoominc); signalhandler.send("positionChange", {nosliceupdate:true},that.positionChanger); // why this ...markers? } } return true; }, mouseup: function(){ } }, {hideCurrentval:true} ); layoutbar.attach(layoutbar.$slideslices) layoutbar.attach(layoutbar.$center); layoutbar.attach(layoutbar.$slidezoom) layoutbar.$resetzoom = $("<span class='KViewPort_tool_layout'> <i class='fa fa-reply fa-1x'></i> </span>"); layoutbar.$resetzoom.mousedown(function(ev){ KViewer.resetCrossHair() }) layoutbar.attach(layoutbar.$resetzoom) layoutbar.$zoomin.on("mousedown", function(e) { if (layoutbar.$zoomin.iid != -1) clearInterval(layoutbar.$zoomin.iid); var maxex = that.computeMaxExtentFac() layoutbar.$zoomin.fac = 1.002; if (gl_enabled) { layoutbar.$zoomin.iid = setInterval(function() { that.gl.camera.inertialRadiusOffset -= maxex * (1 - layoutbar.$zoomin.fac); if (isNaN(that.gl.camera.inertialRadiusOffset)) that.gl.camera.inertialRadiusOffset = 1; that.gl.activateRenderLoop(); that.gl.setQuality() }, 0); } else if (that.mosaicview.active) { var amount = 1; that.mosaicview.zoom += ((amount > 0) ? -1 : 1) * 0.3 * scrollSpeed; if (that.mosaicview.zoom > 1) that.mosaicview.zoom = 1; setCanvasLayout(); drawHairCross(); } else { layoutbar.$zoomin.iid = setInterval(function() { $(".markerpoint,.markerruler").css('display','none') signalhandler.send("setZoom", layoutbar.$zoomin.fac); signalhandler.send("positionChange", {nosliceupdate:true},that.positionChanger); if (layoutbar.$zoomin.fac < 1.01) layoutbar.$zoomin.fac += 0.0002; }, 0); } }); layoutbar.$zoomin.on("mouseup mouseleave", function(e) { clearInterval(layoutbar.$zoomin.iid); layoutbar.$zoomin.iid = -1; }); layoutbar.$zoomout.on("mousedown", function(e) { if (layoutbar.$zoomout.iid != -1) clearInterval(layoutbar.$zoomin.iid); var maxex = that.computeMaxExtentFac() layoutbar.$zoomout.fac = 0.998; if (gl_enabled) { layoutbar.$zoomout.iid = setInterval(function() { that.gl.camera.inertialRadiusOffset += maxex * (1 - layoutbar.$zoomin.fac); if (isNaN(that.gl.camera.inertialRadiusOffset)) that.gl.camera.inertialRadiusOffset = 1; that.gl.activateRenderLoop(); that.gl.setQuality() }, 0); } else if (that.mosaicview.active) { var amount = -1; that.mosaicview.zoom += ((amount > 0) ? -1 : 1) * 0.3 * scrollSpeed; if (that.mosaicview.zoom > 1) that.mosaicview.zoom = 1; if (KViewer.mainViewport != -1) signalhandler.send("mosaic_changelayout",that.mosaicview); else { setCanvasLayout(); drawHairCross(); } } else { layoutbar.$zoomout.iid = setInterval(function() { $(".markerpoint,.markerruler").css('display','none') signalhandler.send("setZoom", layoutbar.$zoomout.fac); signalhandler.send("positionChange", {nosliceupdate:true},that.positionChanger); if (layoutbar.$zoomout.fac > 0.99) layoutbar.$zoomout.fac -= 0.0002; }, 0); } }); layoutbar.$zoomout.on("mouseup mouseleave", function(e) { clearInterval(layoutbar.$zoomout.iid); }); layoutbar.$zoomin.hide(); layoutbar.$zoomout.hide(); layoutbar.$moszoomin = $("<span class='KViewPort_tool_layout'> <i class='fa fa-plus'></i> </span>").hide().click( function(e) { var amount = -1; that.mosaicview.nx_cont += ((amount > 0) ? -1 : 1); if (that.mosaicview.nx_cont < 2) that.mosaicview.nx_cont = 2; that.mosaicview.nx = Math.round(that.mosaicview.nx_cont); if (KViewer.mainViewport != -1) signalhandler.send("mosaic_changelayout",that.mosaicview); else { setCanvasLayout(); drawHairCross(); } }); layoutbar.$moszoomout = $("<span class='KViewPort_tool_layout'> <i class='fa fa-minus'></i> </span>").hide().click( function(e) { var amount = 1; that.mosaicview.nx_cont += ((amount > 0) ? -1 : 1); if (that.mosaicview.nx_cont < 2) that.mosaicview.nx_cont = 2; that.mosaicview.nx = Math.round(that.mosaicview.nx_cont); if (KViewer.mainViewport != -1) signalhandler.send("mosaic_changelayout",that.mosaicview); else { setCanvasLayout(); drawHairCross(); } }); layoutbar.$leftrot = $("<span class='KViewPort_tool_layout'> <i class='fa fa-rotate-left'></i> </span>").hide(); layoutbar.$rightrot = $("<span class='KViewPort_tool_layout'> <i class='fa fa-rotate-right'></i> </span>").hide(); function ani3D(e, dir) { layoutbar.$rightrot.removeClass('KViewPort_tool_enabled'); layoutbar.$leftrot.removeClass('KViewPort_tool_enabled'); if (that.gl.animate3D(dir)) $(e).addClass('KViewPort_tool_enabled'); } layoutbar.$leftrot.click(function() { ani3D(this, +1) }); layoutbar.$rightrot.click(function() { ani3D(this, -1) }); layoutbar.attach(layoutbar.$moszoomin) .attach(layoutbar.$moszoomout) .attach(layoutbar.$rightrot) .attach(layoutbar.$leftrot); layoutbar.showLayout3D = function() { layoutbar.$leftrot.show(); layoutbar.$rightrot.show(); if ( layoutbar.$shortcut3d) layoutbar.$shortcut3d.text("2D"); layoutbar.$slicing.hide(); layoutbar.$slideslices.hide(); layoutbar.$center.hide(); } layoutbar.hideLayout3D = function() { layoutbar.$leftrot.hide(); layoutbar.$rightrot.hide(); if ( layoutbar.$shortcut3d) { layoutbar.$shortcut3d.show(); layoutbar.$shortcut3d.text("3D"); } layoutbar.$slicing.show(); layoutbar.$slideslices.show(); layoutbar.$center.show(); } // this should be implemented at another place ( in roiPanel) var ROIadder = function(_that) { return KContextMenu( function() { var upperadder var loweradder var $menu = $("<ul class='menu_context small'>") .append($("<hr width='100%'> ")) .append($("<span> &nbsp <i class='fa leftaligned fa-pencil-square-o fa-1x'></i> ROI </span>")) .append($("<hr width='100%'> ")) .append($("<li onchoice='empty' > create empty </li>")) .append(upperadder= $("<li onchoice='upper' > larger than lower limit </li>")) .append(loweradder=$("<li onchoice='lower' > lower than lower limit </li>")) .append($("<hr width='100%'> ")) .append($("<span> &nbsp <i class='fa leftaligned fa-shopping-basket fa-1x'></i> Miscellaneous </span>")) .append($("<hr width='100%'> ")) var currentid = _that.currentFileID; var matrices_available = []; if (that.currentFileID != currentid) matrices_available.push({n:that.currentFilename,id:that.currentFileID}) for (var i = 0; i < that.ROIs.length;i++) if (that.ROIs[i].roi.fileID != currentid) matrices_available.push({id:that.ROIs[i].roi.fileID,n:that.ROIs[i].roi.filename}) for (var i = 0; i < that.overlays.length;i++) if (that.overlays[i].currentFileID != currentid) matrices_available.push({n:that.overlays[i].currentFilename,id:that.overlays[i].currentFileID}) if (matrices_available.length>0) { var str_upper = ""; var str_lower = ""; for (var i = 0; i < matrices_available.length;i++) { str_upper += "<li onchoice='upper_"+ matrices_available[i].id +"'> " + matrices_available[i].n + " </li> " str_lower += "<li onchoice='lower_"+ matrices_available[i].id +"'> " + matrices_available[i].n + " </li> " } upperadder.append($(" <ul> " + str_upper +" </ul>" )) loweradder.append($(" <ul> " + str_lower +" </ul>" )) } if (_that.nii.sizes[3]%3 == 0) { var sel = _that.showcolored ? 'check-' : ''; var type = _that.showcolored_type; $menu.append($("<li onchoice='rgbinterpret' > RGB interpret <i class='fa fa-caret-right'></i> <ul> " + "<li onchoice='rgbinterpret' > colored <i onchoice='lock' class='fa fa-"+sel+"square-o'></i> </li>" + "<li onchoice='type_rgbinterpret_raw' > raw <i onchoice='lock' class='fa fa-"+((type=="raw") ? 'check-' : '')+"circle-o'></i> </li>" + "<li onchoice='type_rgbinterpret_RGB' > RGB <i onchoice='lock' class='fa fa-"+((type=="RGB") ? 'check-' : '')+"circle-o'></i> </li>" + "<li onchoice='type_rgbinterpret_BRG' > BRG <i onchoice='lock' class='fa fa-"+((type=="BRG") ? 'check-' : '')+"circle-o'></i> </li>" + "<li onchoice='type_rgbinterpret_GBR' > GBR <i onchoice='lock' class='fa fa-"+((type=="GBR") ? 'check-' : '')+"circle-o'></i> </li>" + "<li onchoice='type_rgbinterpret_GRB' > GRB <i onchoice='lock' class='fa fa-"+((type=="GRB") ? 'check-' : '')+"circle-o'></i> </li>")); } if (_that.refSurfView != undefined) { var showview = ""; if (!_that.refSurfView.toolbarAttached) showview= " <i onchoice='showisoview' class='fa button' style='right:30px;'>show view</i> " $menu.append($("<li onchoice='iso' > remove isosurface "+showview+" </li>")); } else $menu.append($("<li onchoice='iso' > create isosurface </li>")); if (_that.outlines == undefined) $menu.append($("<li onchoice='outline' > show contours </li>")); else { $menu.append($("<li onchoice='outline' > hide contours </li>")); $menu.append($("<li onchoice='contcol' > > contour color </li>")); } if (_that.nii.sizes[3]%3 == 0) $menu.append($("<li onchoice='tracking' >create fiber tracking </li>")); $menu.append($("<li onchoice='refetch' > refetch file </li>")); if (_that.content && _that.content.refvisit_tck) $menu.append($("<li onchoice='unlinktck' > unlink fiber visits </li>")); return $menu; }, function(str, ev) { function arrived(fobj) { master.iterateMedViewers(function(m) { if (_that.currentFileID == m.currentFileID) m.setContent(fobj, {intent: { ROI: true } }); else for (var k = 0; k < m.overlays.length; k++) { if (_that.currentFileID == m.overlays[k].currentFileID) { m.setContent(fobj, {intent: {ROI: true}}); return; } } }); that.ROIs[that.ROIs.length - 1].makeCurrent(); } if (str == undefined) return; if (str == "unlinktck") { if (_that.content.refvisit_tck.visitworker != undefined) { _that.content.refvisit_tck.visitworker.kill(); _that.content.refvisit_tck.visitworker = undefined; } if (_that.content.refvisit_tck.visitworker_terms != undefined) { _that.content.refvisit_tck.visitworker_terms.kill(); _that.content.refvisit_tck.visitworker_terms = undefined; } _that.content.refvisit_tck = undefined; } else if (str.substring(0,5) == "upper" | str.substring(0,5) == "lower" ) { var typ = str.substring(0,5); if (str.length == 5) master.roiTool.pushROI(_that.currentFileID, "mask_"+ _that.currentFilename, typ + _that.histoManager.clim[0], arrived); else { var id = str.substring(6) $(document.body).addClass("wait"); setTimeout( function() { master.roiTool.pushROI(id, "mask_"+ _that.currentFilename,undefined, function(fobj) { var thres = _that.histoManager.clim[0]; var eqfun; if (typ == "lower") eqfun = function(x) { return x < thres; } else eqfun = function(x) { return x > thres; } var nii = _that.nii; var roi = fobj.content; var offset = 0; if (nii.currentTimePoint) offset = nii.currentTimePoint.t * nii.sizes[0] * nii.sizes[1] * nii.sizes[2] ; var A = (math.multiply(math.inv(nii.edges), roi.edges))._data; for (var z = 0; z < roi.sizes[2]; z++) for (var y = 0; y < roi.sizes[1]; y++) for (var x = 0; x < roi.sizes[0]; x++) { if (eqfun(trilinInterp(nii, x, y, z, A, offset))) roi.data[roi.sizes[1] * roi.sizes[0] * z + roi.sizes[0] * y + x] = 1; } arrived(fobj) $(document.body).removeClass("wait"); } ); },0); } } else if (str == "empty") master.roiTool.pushROI(_that.currentFileID, "mask_untitled", undefined, arrived); else if (str == "iso") that.attachSurfaceRef(_that,_that.content); else if (str == 'rgbinterpret') { _that.showcolored = !_that.showcolored; signalhandler.send("updateImage",{id:_that.currentFileID}); } else if (str.substring(0,17) == 'type_rgbinterpret') { _that.showcolored_type = str.substring(18); signalhandler.send("updateImage",{id:_that.currentFileID}); } else if (str == "showisoview") { if (_that.refSurfView && !_that.refSurfView.toolbarAttached) { ev.preventDefault(); ev.stopImmediatePropagation(); that.toolbar.append(_that.refSurfView.divs,'surface') _that.refSurfView.toolbarAttached = true; } } else if (str == "tracking") { if (that.isGLenabled()) createfibview() else toggle3D(undefined,createfibview); function createfibview() { var filename = _that.currentFilename.replace(".nii","").replace(".gz","") + ".tck"; var imageStruct = {filename:filename,content:{tracts:[ ]} } ; var fv = master.obj3dTool.createFiberView(imageStruct,that,{ dirvolref: _that,isParentView:true }); that.objects3D.push(fv); } } else if (str == "outline") { var contvis = _that.outlines == undefined; if (!ev.shiftKey) { var ev_ = ev; master.iterateMedViewers(function(m) { for (var k = 0; k < m.overlays.length; k++) if (_that.currentFileID == m.overlays[k].currentFileID) { m.overlays[k].setOutlines(contvis,ev_) ev_ = undefined break; } }); } else _that.setOutlines(contvis,ev) } else if (str == "refetch") { KViewer.dataManager.refetchFile(_that.currentFileinfo, that.viewport.progressSpinner) } else if (str == "contcol") { _that.chooseContColor(ev); } }); } that.quivers = []; that.addQuiver = function(histoobj) { for (var k = 0; k < that.quivers.length;k++) { if (that.quivers[k] == histoobj) return; } that.quivers.push(histoobj); } that.removeQuiver = function(histoobj) { for (var k = 0; k < that.quivers.length;k++) { if (that.quivers[k] == histoobj) { that.quivers.splice(k,1); return; } } } that.addAsROIMenu = ROIadder(that); /* this was used as a roi adder per viewport var toolbarRoi = {}; toolbarRoi.$container = $("<div class='KViewPort_roiAdder' style='position:relative;right:0px;'>add Roi</div>").appendTo(that.toolbar.$container).click(function(ev){return false;}) .hide(); toolbarRoi.$addroi = $("<div class='KViewPort_tool'> <i class='fa fa-plus fa-1x'> </div>").appendTo(toolbarRoi.$container ) .appendTooltip("create new roi from this viewport image").click( function(){master.roiTool.createEmptyRoi(that, 'untitled');} ); */ // old: allow creation of roi here toolbar.$addroi = $("<div class='KViewPort_tool'> <i class='fa fa-cog fa-1x'> </div>").click(that.addAsROIMenu); //toolbar.$addroi = $("<div class='KViewPort_tool'> <i class='fa fa-pencil fa-1x'> </div>") //.appendTooltip("roitool_open").click(function() { // master.roiTool.show() //}); toolbar.$mainViewportSelector = $("<div myid='KViewPort_tool_toggleMainViewport' class='KViewPort_tool'><i class='fa fa-maxcdn fa-1x'></i></div>") .appendTooltip("masterviewport").click(function() { master.toggleMainViewport(viewport.viewPortID); }); toolbar.$movie = $("<div class='KViewPort_movie_tool'><i class='fa fa-play fa-1x'></i></div>").click(function() { toggleMovie(this); }); toolbar.$movie.hide(); toolbar.attach(toolbar.$addroi).attach(toolbar.$mainViewportSelector).attach(toolbar.$movie); /************************* movie stuff *********************/ that.movieSpeedFPS = 5; function changemoviespeed() { toggleMovie(); if(that.movieGlobalMode) { master.iterateMedViewers(function(m) { if (m.nii !=undefined && m.$timediv.maxt > 1 & m.movieGlobalMode) { m.$timeinput_fps.val( $timeinput_fps.val() ); m.movieSpeedFPS = $timeinput_fps.val(); } }); } else { that.movieSpeedFPS = $timeinput_fps.val(); } toggleMovie(); } var $timeinput_fps = $("<input class='KViewPort_tool' style='' type='' min=1 max=100000 value=" + that.movieSpeedFPS + " />") .appendTooltip("Movie Speed (frames per second") .on('change input', changemoviespeed); that.$timeinput_fps = $timeinput_fps; /* movie can be played - globally: link all viewports (default), given by master.currentTimePointGlobal, master.movieIsPlayedGlobal - individually */ var $setMovieGlobalMode = $("<div class='KViewPort_movie_tool'><i class='fa fa-link fa-1x'></i></div>").click( setMovieGlobalMode ); that.movieGlobalMode = 1; function setMovieGlobalMode(state) { // do not allow to change mode during play, otherwise will be a mess if(movieIsPlayed | master.movie.isPlayed) return false that.movieGlobalMode = !that.movieGlobalMode; if(!that.movieGlobalMode) { $setMovieGlobalMode.css('background', 'red'); } else { $setMovieGlobalMode.css('background', ''); } } var $timeinput = $("<input class='KViewPort_tool KViewPort_tool_movie_slider' type='range' min=0 max=100 value=0>"); var $timeCurrent = $("<span class='KViewPort_movie_tool' style='width:20px; background: none;color:white;'>0</span>"); var $timediv = $("<div class='KViewPort_toolbar KTimeRangeSlider'> </div>").appendTo($container) .append($timeCurrent).append($timeinput).append(toolbar.$movie).append($timeinput_fps).append($setMovieGlobalMode) .hide(); that.$timediv = $timediv; that.$timediv.$timeinput = $timeinput; // this is called when new image is loaded $timediv.update = function() { var maxt = 1; if (that.nii != undefined && that.nii.numTimePoints > 1) maxt = that.nii.numTimePoints; for (var k = 0; k < that.overlays.length; k++) if (that.overlays[k].nii.numTimePoints > maxt) maxt = that.overlays[k].nii.numTimePoints; for (var k = 0; k < that.ROIs.length; k++) if (that.ROIs[k].nii.numTimePoints > maxt) maxt = that.ROIs[k].nii.numTimePoints; if (maxt > 1) { $timediv.maxt = maxt; that.toolbar.$movie.show(); $timediv.show(); $timeinput.attr("max", maxt-1 ); that.setMovieState(movieIsPlayed | master.movie.isPlayed); } else { $timediv.maxt = 1; that.toolbar.$movie.hide(); $timediv.hide(); } } KMouseSlider($timeinput_fps, {min:1, incrementPerPixel:0.1}); $timeinput.on('change input', function(){setCurrentTimePoint( $(this).val() ); } ); //$timeCurrent.on('mousewheel', timeinputwheel) //$timediv.on('mousewheel', timeinputwheel) if (/Firefox/i.test(navigator.userAgent)) $timediv.get(0).addEventListener("DOMMouseScroll", timeinputwheel, false); else $timediv.get(0).addEventListener("mousewheel", timeinputwheel, false); function timeinputwheel(e) { if(e.wheelDelta || -e.detail) var amount = (e.wheelDelta || -e.detail) > 0 ?1:-1; else var amount = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0 ?1:-1; var newval = parseInt($timeinput.val()) + amount; if(newval >= 0) { setCurrentTimePoint(newval) } e.preventDefault(); e.stopPropagation(); return false; } // set the current time global/local from gui or from an iteration loop function setCurrentTimePoint(val) { if(that.movieGlobalMode) { master.movie.currentTimePoint = val; master.iterateMedViewers(function(m) { if (m.nii !=undefined & m.movieGlobalMode) { m.updateCurrentTimePoint(val); } }); } else { that.updateCurrentTimePoint(val); } } that.updateCurrentTimePoint = function(val) { if ($timediv.maxt <= 1) return; if( val > $timediv.maxt-1) val = $timediv.maxt-1; if(val < 0) val = 0; val = parseInt(val); if (that.nii.numTimePoints > 1 && val < that.nii.numTimePoints ) that.nii.currentTimePoint.t = val; $timeinput.val( val ); $timeCurrent.text( val ); for (var k = 0; k < that.overlays.length; k++) { var xnii = that.overlays[k].nii; if (xnii.numTimePoints > 1 && xnii.numTimePoints >= val) { xnii.currentTimePoint.t = val; that.overlays[k].$timeinput.val(val); signalhandler.send("overlay_climChange", { id: that.overlays[k].currentFileID, val: that.overlays[k].histoManager.clim }); } } for (var k = 0; k < that.ROIs.length; k++) { var xnii = that.ROIs[k].nii; if (xnii.numTimePoints > 1 && xnii.numTimePoints >= val) { xnii.currentTimePoint.t = val; that.ROIs[k].$timeinput.val(val); signalhandler.send("updateImage", { id: that.ROIs[k].roi.fileID, }); } } // seems to be simpelst way to initiate all updates signalhandler.send("climChange", { id: that.currentFileID, val: that.histoManager.clim, }); if(KViewer.curveTool.enabled) KViewer.curveTool.updateCurrentTimePoint(val); } function toggleMovie( ) { // global play if(that.movieGlobalMode) { master.movie.maxNumTimePoints = 1; master.iterateMedViewers(function(m) { if (m.nii !=undefined && m.$timediv.maxt > 1 && m.movieGlobalMode) { m.setMovieState( !master.movie.isPlayed ); if(m.$timediv.maxt > master.movie.maxNumTimePoints) master.movie.maxNumTimePoints = m.$timediv.maxt; } }); if(master.movie.isPlayed) { clearInterval( master.movie.timerId); master.timerId = false; } else { master.movie.timerId = setInterval(function() { if (typeof executeImageWorker != "undefined" && executeImageWorker.createIsoSurf_running) return; master.movie.currentTimePoint = ( master.movie.currentTimePoint + 1 ) % master.movie.maxNumTimePoints; master.iterateMedViewers(function(m) { if (m.nii !=undefined && m.$timediv.maxt > 1 && m.movieGlobalMode) { m.updateCurrentTimePoint(master.movie.currentTimePoint); } }); }, 1000 * 1 / that.movieSpeedFPS); } master.movie.isPlayed = !master.movie.isPlayed; } else // local play { if(movieIsPlayed) { clearInterval( timerId); timerId = false; that.setMovieState(false); } else { timerId = setInterval(function() { that.updateCurrentTimePoint( (parseInt($timediv.$timeinput.val()) + 1) % $timediv.maxt ); }, 1000 * 1 / that.movieSpeedFPS); that.setMovieState(true); } } } // set movie playing state in gui that.setMovieState = function(state ) { movieIsPlayed = state; if (movieIsPlayed) toolbar.$movie.find('i').removeClass('fa-play').addClass('fa-stop'); else toolbar.$movie.find('i').addClass('fa-play').removeClass('fa-stop'); } /* signalhandler.attach("positionChange", function() { if (that.$timediv.nii) { $timeinput.val(that.$timediv.nii.currentTimePoint.t); $timeCurrent.html(that.$timediv.nii.currentTimePoint.t); } }) */ var movieIsPlayed = false; var timerId = 0; /* get full filename */ that.getFullFilename = function() { if(that.currentFileinfo == undefined) return; if(that.currentFileinfo.SubFolder!=="") return that.currentFileinfo.SubFolder + "/" + that.currentFileinfo.Filename; else return that.currentFileinfo.Filename; } /************************* getCurrentReadDirections *********************/ that.getCurrentReadDirections = function() { var nii = that.nii; if (slicingDimOfWorld == 0) { return [nii.arrayReadDirection[nii.invPermOrder[1]] , nii.arrayReadDirection[nii.invPermOrder[2]] ]; } if (slicingDimOfWorld == 1) { return [nii.arrayReadDirection[nii.invPermOrder[0]] , nii.arrayReadDirection[nii.invPermOrder[2]] ]; } if (slicingDimOfWorld == 2) { return [nii.arrayReadDirection[nii.invPermOrder[0]] , nii.arrayReadDirection[nii.invPermOrder[1]] ]; } } /************************* world position management *********************/ function getWorldPosition() { if (worldLockedToMaster & master.globalCoordinates) return master.currentPoint; else return customPoint; } that.getWorldPosition = getWorldPosition; function setWorldPosition(p) { if (worldLockedToMaster & master.globalCoordinates ) master.currentPoint = p; else customPoint = p; } that.setWorldPosition = setWorldPosition; var worldLockedToMaster = true; var customPoint = math.matrix([0,0,0,1]) function changeWorldLock(e) { var $target = toolbar.$lock;//$(e.target); if (!$target.hasClass('fa')) $target = $target.find("i"); $target.toggleClass('fa-lock'); $target.toggleClass('fa-unlock'); if (worldLockedToMaster) customPoint = math.matrix(getWorldPosition()); worldLockedToMaster = !worldLockedToMaster; drawSlice({ mosaicdraw: true }); } // attach misc stuff var $infobar = $("<div draggable=true id='KViewPort_infobar' class = 'KViewPort_infoDIV'></div>").appendTo($topRow); $infobar.attr("draggable", 'true'); that.$infobar = $infobar; that.$infobar.on("click",function(ev) { if (KViewer.zoomedViewport != -1) { if (!that.viewport.isZoomed()) { KViewer.unZoomViewport(); that.viewport.zoomViewPort(); } else that.viewport.zoomViewPort(); } }); that.$infobar.on("mousedown",function(ev) { if (ev.button == 2) showInfoContextNifti(that,ev) }); var $LeftRightSign = $("<div class='KViewPort_description'>R</div>").hide().appendTo($container); that.$LeftRightSign = $LeftRightSign; // attach the scrollAccel var scrollSpeed = 1; var $scrollAccelerator = $("<div class='KViewPort_scrollAccelerator' ></div>").appendTo(that.layoutbar.$container) that.layoutbar.$container.mouseenter(function(ev) { ev.preventDefault(); scrollSpeed = 4; //$scrollAccelerator.text('scroll speed +' +scrollSpeed); }); that.layoutbar.$container.mouseleave(function(ev) { scrollSpeed = 1; //$scrollAccelerator.text(''); }); // attach the canvas var $canvas = $("<canvas class='KViewPort_canvas'></canvas>").appendTo($canvascontainer); that.$canvas = $canvas; var ctx = $canvas.get(0).getContext("2d"); var $canvas3D = $("<canvas class='KViewPort_canvas3D'></canvas>").appendTo($container); that.$canvas3D = $canvas3D; $canvas3D.hide(); var gl; var gl_enabled = false; that.isGLenabled = function() { return gl_enabled; } // attach the haircross var haircross = { X: { t: "X", tilt: 0 }, nX: { t: "X", tilt: 0 }, Y: { t: "Y", tilt: 0 }, nY: { t: "Y", tilt: 0 }, C: {} }; that.haircross = haircross; //haircross.C.$circle = $("<div class='haircrossFocus'></div>").appendTo($canvascontainer); //haircross.C.$circle = $("<div class='haircrossFocus_new'><i class='fa fa-3x fa-refresh'></i><i class='fa fa-3x fa-arrows'></i><div></div></div>").appendTo($canvascontainer); haircross.C.$circle = $("<div class='haircrossFocus_new'></div>").appendTo($canvascontainer); haircross.C.$circle_center = $("<i class='fa fa-3x fa-refresh'></i>").appendTo(haircross.C.$circle).append($("<i class='fa fa-3x fa-arrows'></i>")); haircross.C.$circle_rotIndicator = $("<div class=''></div>").appendTo(haircross.C.$circle); haircross.X.lineN = new KHaircross(); haircross.X.lineN.$main.appendTo($canvascontainer) haircross.Y.lineN = new KHaircross(); haircross.Y.lineN.$main.appendTo($canvascontainer); that.overlays = []; that.objects3D = []; that.ROIs = []; that.ROIs_temp = []; that.atlas = []; that.currentROI = undefined; that.getCurrentROIobj = function() { for (var k = 0; k < that.ROIs.length; k++) { if (that.ROIs[k].roi == that.currentROI) return that.ROIs[k]; } return undefined; } var sx = 10; var sy = 10; var xd