@galaxyproject/nora
Version:
NORA Medical Imaging Viewer
1,386 lines (1,136 loc) • 426 kB
JavaScript
// ======================================================================================
// ======================================================================================
// ============= 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) + ' ' + nii.sizes[1].toFixed(0) + ' ' + nii.sizes[2].toFixed(0) + ' ' + nii.sizes[3].toFixed(0);
else
msz = "matrix: " + nii.sizes[0].toFixed(0) + ' ' + nii.sizes[1].toFixed(0) + ' ' + 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) + ' ' + nii.voxSize[1].toFixed(1) + ' ' + 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>   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>   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'>    </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>   <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>   <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