@galaxyproject/nora
Version:
NORA Medical Imaging Viewer
1,314 lines (1,077 loc) • 521 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;
that.visible = true;
that.isFlatMap = false;
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.toggle = function(e)
{
var vis = !that.visible;
if (!e.shiftKey)
{
master.iterateMedViewers(function(m)
{
if (that.currentFileID == m.currentFileID)
{
m.setVisibility(vis)
}
});
}
else
that.setVisibility(vis)
}
that.setVisibility = function(visible)
{
if (!visible)
{
that.visible = false;
toolbar.$eye.css('color', 'red');
}
else
{
that.visible = true;
toolbar.$eye.css('color', '');
}
that.drawSlice({
mosaicdraw: true
});
}
that.viewContextMenu = new KContextMenu(
function() {
var $menu = $("<ul class='menu_context'>");
var name = ['Sagittal', '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.$eye = $("<div class='KViewPort_tool'> <i class='fa fa-eye fa-1x'> </div>").click(that.toggle);
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.$eye).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",{viewer:that}); }
).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, startBox: that.mosaicview.clipratio,
currentpos: getCanvasCoordinates(getWorldPosition()),
}
},
mousemove:function(ev,dx,dy,mousedownvar, lastdx, lastdy)
{
if (gl_enabled)
{
var zoominc = 1 - lastdy*0.001;
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)
{
var sbox = mousedownvar.startBox;
var cpos = mousedownvar.currentpos;
var zoomy = 1+0.1*dy;
sbox[0] = (sbox[0]-cpos.x_norm)*zoomy + cpos.x_norm;
sbox[2] = (sbox[2]-cpos.x_norm)*zoomy + cpos.x_norm;
sbox[1] = (sbox[1]-cpos.y_norm)*zoomy + cpos.y_norm;
sbox[3] = (sbox[3]-cpos.y_norm)*zoomy + cpos.y_norm;
if (sbox[0]<0) sbox[0] = 0;
if (sbox[1]<0) sbox[1] = 0;
if (sbox[2]>1) sbox[2] = 1;
if (sbox[3]>1) sbox[3] = 1;
if (sbox[2]-sbox[0] < 0.0001 | sbox[3]-sbox[1] < 0.0001 )
{
sbox = [0,0,1,1];
alertify.error("are you nuts")
}
that.mosaicview.clipratio = sbox;
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 &
!ev.shiftKey & !that.isFlatMap)
{
signalhandler.send("setZoom", zoominc );
signalhandler.send("positionChange", {nosliceupdate:true},that.positionChanger);
}
else
{
setZoom(zoominc);
signalhandler.send("positionChange", {nosliceupdate:true},that.positionChanger);
}
}
return true;
},
mouseup: function(){
signalhandler.send("positionChange", {},that.positionChanger);
}
},
{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){
var p = niiOriginal.centerWorld
if (that.isFlatMap)
{
customPoint = p;
p = mapFlatMapCoordinate(p)
}
KViewer.resetCrossHair(ev,p)
})
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');
}
function setGLprops(props)
{
var cid = setInterval(tryit,300)
var cnt = 0;
function tryit()
{
cnt++;
if (that.gl != undefined)
{
that.gl.setprops(props)
clearInterval(cid)
}
else if (cnt > 10)
clearInterval(cid)
}
}
that.setGLprops = setGLprops
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>" +
"<li onchoice='type_rgbinterpret_SOS' > SOS <i onchoice='lock' class='fa fa-"+((type=="SOS") ? '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.type != "mainview")
{
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>"));
$menu.append($("<hr width='100%'> "))
$menu.append($("<li onchoice='reslice' > reformat/reslice image </li>"));
if (KViewer.reorientationMatrix.notID)
$menu.append($("<li onchoice='burnin' > burnin current affine </li>"));
$menu.append($("<li onchoice='download_header_info' > download header info </li>"));
$menu.append($("<li onchoice='centermatrix' > center matrix to current position </li>"));
var ROIs = KViewer.roiTool.ROIs
var rois = Object.keys(ROIs);
if (rois.length > 0)
{
var $submenu = $("<ul> </ul>")
var $item = $("<li onchoice='...' >crop/mask<i onchoice='lock' class='fa fa-caret-right'></i>").appendTo($menu)
$item.append($submenu)
for (var k = 0; k < rois.length;k++)
$submenu.append($("<li onchoice='mask_ROI_"+rois[k]+"' >"+ROIs[rois[k]].filename+" </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")
{
unlinktck(_that)
}
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 = { fileinfo: { patients_id: that.currentFileinfo.patients_id,
studies_id: that.currentFileinfo.studies_id },
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 == "reslice")
{
alertify.prompt("New resolution of image in mm:", function(e, str) {
if (e)
{
var fac = eval(str);
var fi = KViewer.dataManager.getFile(_that.currentFileID)
var vsz = fi.content.voxSize
resliceNifti(fi,[fac[0]/vsz[0],fac[1]/vsz[1],fac[2]/vsz[2]]);
var sp = fi.filename.split(".")
sp[0] = sp[0] + '_reformated';
fi.filename = sp.join(".");
if (fi.fileinfo && fi.fileinfo.Filename)
fi.fileinfo.Filename = fi.filename;
fi.editable = true;
fi.modified = true;
KViewer.cacheManager.update();
KViewer.setViewPortLayout()
}
},"[2,2,2]");
}
else if (str == "burnin")
{
var fi = KViewer.dataManager.getFile(_that.currentFileID)
resliceNifti_affine(fi,(KViewer.reorientationMatrix.matrix));
var sp = fi.filename.split(".")
sp[0] = sp[0] + '_reformated';
fi.filename = sp.join(".");
if (fi.fileinfo && fi.fileinfo.Filename)
fi.fileinfo.Filename = fi.filename;
fi.editable = true;
fi.modified = true;
KViewer.navigationTool.resetTransform();
KViewer.cacheManager.update();
KViewer.setViewPortLayout()
}
else if (str == "centermatrix")
{
if (Object.keys(KViewer.navigationTool.movingObjs).length > 0)
alertify.confirm("There are already moving images defined in the navigation. When you proceed, all navigation information will be discarded.",
function(e) {
if (e)
centermatrix()
})
else
centermatrix();
function centermatrix()
{
var fi = KViewer.dataManager.getFile(_that.currentFileID)
for (var k in KViewer.navigationTool.movingObjs) delete KViewer.navigationTool.movingObjs[k];
KViewer.navigationTool.movingObjs[fi.fileID] = fi;
KViewer.navigationTool.updateMoving();
var csz = fi.content.sizes.slice(0,3).map((x)=>x*0.5-0.5).concat([1])
var center = kmath.multiply(fi.content.edges, csz)
var dif = kmath.add(KViewer.currentPoint,center,-1);
KViewer.reorientationMatrix.matrix._data[0][3] = -dif._data[0];
KViewer.reorientationMatrix.matrix._data[1][3] = -dif._data[1];
KViewer.reorientationMatrix.matrix._data[2][3] = -dif._data[2];
signalhandler.send("positionChange")
}
}
else if (str == "download_header_info")
{
var fi = _that.currentFileinfo
var nii = _that.nii
var hdr = {edges:nii.edges._data,
voxSize:nii.voxSize,
sizes:nii.sizes,
extension:nii.extension}
initiateDownload(JSON.stringify(hdr), fi.Filename.replace(".gz","").replace(".nii","") + "_header.json");
}
else if (str.substring(0,9) == "mask_ROI_")
{
var roiid = str.substring(9);
var fi = KViewer.dataManager.getFile(_that.currentFileID)
var roi = KViewer.dataManager.getFile(roiid)
maskContrastWithROI(fi,roi)
signalhandler.send("updateImage", {
id: fi.fileID,
});
fi.editable = true;
fi.modified = true;
KViewer.cacheManager.update();
function maskContrastWithROI(cobj,roiobj)
{
var nii = cobj.content
var roi = roiobj.content;
roi.A = (math.multiply(math.inv(roi.edges), nii.edges))._data;
for (var k = 0;k < nii.sizes[3];k++)
for (var z = 0; z < nii.sizes[2]; z++)
for (var y = 0; y < nii.sizes[1]; y++)
for (var x = 0; x < nii.sizes[0]; x++)
{
var v = trilinInterp(roi, x, y, z, roi.A, 0);
nii.data[nii.widheidep*k + nii.sizes[1] * nii.sizes[0] * z + nii.sizes[0] * y + x] *= v;
}
}
}
else if (str == "contcol")
{
_that.chooseContColor(ev);
}
});
}
function unlinktck(_that)
{
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;
}
that.unlinktck = unlinktck;
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'>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)
}
e.preventDefault();
e.stopPropagation();
return false;
}
// set the current time global/local from gui or from an iteration loop
function setCurrentTimePoint(val,e)
{
var global = that.movieGlobalMode;
if (e != undefined && e.shiftKey)
global = false;
if (global)
{
master.movie.currentTimePoint = val;
master.iterateMedViewers(function(m)
{
if (m.nii !=undefined & m.movieGlobalMode & global)
{
m.updateCurrentTimePoint(val);
}
});
}
else
{
that.updateCurrentTimePoint(val);
}
}
that.updateCurrentTimePoint = function(val)
{
var ovls = that.overlays;
for (var k = 0; k < that.objects3D.length;k++)
if (that.objects3D[k].overlays && that.objects3D[k].overlays.length > 0)
ovls = ovls.concat(that.objects3D[k].overlays)
for (var k = 0; k < ovls.length; k++)
{
var xnii = ovls[k].nii;
if (xnii.numTimePoints > 1 && xnii.numTimePoints >= val)
{
xnii.currentTimePoint.t = val;
ovls