");
- black.css({position:'fixed',top:0,left:0,width:'100%',height:'100%','z-index':5,'background-color':'#222'});
- $('body').append(black);
-
- // configure display mode
- // $("#atlasMaker").removeClass('display-mode');
- $("body").addClass('atlasMaker-fullscreen');
- $("#atlasMaker").detach().appendTo('body');
-
- // me.editMode=1;
- me.resizeWindow();
-
- // configure toolbar for edit mode
- //$("#log").outerHeight($("#tools-side").outerHeight()-$("#log").offset().top-$("#msg").closest("tr").outerHeight());
- me.fullscreen=true;
- } else {
+ if(me.fullscreen==false) {
+ // Enter fullscreen
+ //-----------------
+
+ // add black overlay
+ var black=$("
");
+ black.css({position:'fixed',top:0,left:0,width:'100%',height:'100%','z-index':5,'background-color':'#222'});
+ $('body').append(black);
+
+ // configure display mode
+ // $("#atlasMaker").removeClass('display-mode');
+ $("body").addClass('atlasMaker-fullscreen');
+ $("#atlasMaker").detach().appendTo('body');
+
+ // me.editMode=1;
+ me.resizeWindow();
+
+ // configure toolbar for edit mode
+ //$("#log").outerHeight($("#tools-side").outerHeight()-$("#log").offset().top-$("#msg").closest("tr").outerHeight());
+ me.fullscreen=true;
+ } else {
- // Exit fullscreen
- //----------------
-
- // remove black overlay
- $("#blackOverlay").remove();
-
- // go back to display mode
- $("body").removeClass('atlasMaker-fullscreen');
- // $("#atlasMaker").addClass('display-mode');
- $("#atlasMaker").detach().appendTo('#stereotaxic');
- // me.editMode=0;
- me.resizeWindow();
+ // Exit fullscreen
+ //----------------
+
+ // remove black overlay
+ $("#blackOverlay").remove();
+
+ // go back to display mode
+ $("body").removeClass('atlasMaker-fullscreen');
+ // $("#atlasMaker").addClass('display-mode');
+ $("#atlasMaker").detach().appendTo('#stereotaxic');
+ // me.editMode=0;
+ me.resizeWindow();
- me.fullscreen=false;
- }
- },
+ me.fullscreen=false;
+ }
+ },
/**
* @function render3D
*/
- render3D: function render3D() {
- var me=AtlasMakerWidget;
- var l=me.traceLog(render3D,0,"#f00");if(l)console.log.apply(undefined,l);
-
- // puts a fresh version of the segmentation in localStorage
- localStorage.brainbox=URL.createObjectURL(new Blob([me.encodeNifti()]));
-
- // opens 3d render window
- window.open("/templates/surface.html?path="+me.User.dirname+me.User.atlasFilename,"_blank");
- },
+ render3D: function render3D() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(render3D,0,"#f00");if(l)console.log.apply(undefined,l);
+
+ // puts a fresh version of the segmentation in localStorage
+ localStorage.brainbox=URL.createObjectURL(new Blob([me.encodeNifti()]));
+
+ // opens 3d render window
+ window.open("/templates/surface.html?path="+me.User.dirname+me.User.atlasFilename,"_blank");
+ },
/**
* @function link
*/
- link: function link() {
- var me=AtlasMakerWidget;
- var l=me.traceLog(link,0,"#f00");if(l)console.log.apply(undefined,l);
- window.prompt("Copy to clipboard:", location.href+"&view="+AtlasMakerWidget.User.view+"&slice="+AtlasMakerWidget.User.slice);
- },
+ link: function link() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(link,0,"#f00");if(l)console.log.apply(undefined,l);
+ window.prompt("Copy to clipboard:", location.href+"&view="+AtlasMakerWidget.User.view+"&slice="+AtlasMakerWidget.User.slice);
+ },
/**
* @function upload
*/
- upload: function upload() {
- var me=AtlasMakerWidget;
- var l=me.traceLog(upload,0,"#f00");if(l)console.log.apply(undefined,l);
-
- var inp=$(" ");
- inp.hide();
- $("body").append(inp);
- var input=inp.get(0);
- input.type="file";
- input.onchange=function from_upload(e){
- var name=this.files[0];
- var reader = new FileReader();
- reader.onload = function from_upload(e) {
- var result=e.target.result;
- var nii;
- if(name.name.split('.').pop()=="gz") {
- var inflate=new pako.Inflate();
- inflate.push(new Uint8Array(result),true);
- nii=inflate.result.buffer;
- }
- else
- nii=result;
- var mri=me.loadNifti(nii);
+ upload: function upload() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(upload,0,"#f00");if(l)console.log.apply(undefined,l);
+
+ var inp=$(" ");
+ inp.hide();
+ $("body").append(inp);
+ var input=inp.get(0);
+ input.type="file";
+ input.onchange=function from_upload(e){
+ var name=this.files[0];
+ var reader = new FileReader();
+ reader.onload = function from_upload(e) {
+ var result=e.target.result;
+ var nii;
+ if(name.name.split('.').pop()=="gz") {
+ var inflate=new pako.Inflate();
+ inflate.push(new Uint8Array(result),true);
+ nii=inflate.result.buffer;
+ }
+ else
+ nii=result;
+ var mri=me.loadNifti(nii);
- if( mri.dim[0]!=me.User.dim[0] ||
- mri.dim[1]!=me.User.dim[1] ||
- mri.dim[2]!=me.User.dim[2]) {
- console.log("ERROR: Volume dimensions do not match");
- return;
- }
-
- // copy uploaded data to atlas data
- var i;
- for(i=0;i
");
- $("#finger").addClass("touchDevice");
+ var W=parseFloat($('#atlasMaker canvas').css('width'));
+ var H=parseFloat($('#atlasMaker canvas').css('height'));
+ var w=parseFloat($('#atlasMaker canvas').attr('width'));
+ var h=parseFloat($('#atlasMaker canvas').attr('height'));
+
+ me.Crsr.x=parseInt(w/2);
+ me.Crsr.y=parseInt(h/2);
+
+ me.Crsr.fx=parseInt(w/2)*(W/w);
+ me.Crsr.fy=parseInt(h/2)*(H/h);
+ $("#cursor").css({left:(me.Crsr.x*(W/w))+"px",top:(me.Crsr.y*(H/h))+"px",width:me.User.penSize*(W/w),height:me.User.penSize*(H/h)});
+
+ if(me.flagUsePreciseCursor) {
+ if($("#finger").length==0) {
+ me.container.append("
");
+ $("#finger").addClass("touchDevice");
- // configure touch events for tablets
- $("#finger").on("touchstart",function(e){me.touchstart(e)});
- $("#finger").on("touchend",function(e){me.touchend(e)});
- $("#finger").on("touchmove",function(e){me.touchmove(e)});
-
- // turn off eventual touch events handled by canvas
- me.canvas.ontouchstart=null;
- me.canvas.ontouchmove=null;
- me.canvas.ontouchend=null;
- }
- me.updateCursor();
+ // configure touch events for tablets
+ $("#finger").on("touchstart",function(e){me.touchstart(e)});
+ $("#finger").on("touchend",function(e){me.touchend(e)});
+ $("#finger").on("touchmove",function(e){me.touchmove(e)});
+
+ // turn off eventual touch events handled by canvas
+ me.canvas.ontouchstart=null;
+ me.canvas.ontouchmove=null;
+ me.canvas.ontouchend=null;
+ }
+ me.updateCursor();
- $("#finger").css({left:me.Crsr.fx+"px",top:me.Crsr.fy+"px"});
- } else {
- // remove precise cursor
- $("#finger").remove();
+ $("#finger").css({left:me.Crsr.fx+"px",top:me.Crsr.fy+"px"});
+ } else {
+ // remove precise cursor
+ $("#finger").remove();
- // configure touch events for tablets
- me.canvas.ontouchstart=me.touchstart;
- me.canvas.ontouchmove=me.touchmove;
- me.canvas.ontouchend=me.touchend;
- }
- },
+ // configure touch events for tablets
+ me.canvas.ontouchstart=me.touchstart;
+ me.canvas.ontouchmove=me.touchmove;
+ me.canvas.ontouchend=me.touchend;
+ }
+ },
/**
* @function updateCursor
*/
- updateCursor: function updateCursor() {
- var me=AtlasMakerWidget;
- var l=me.traceLog(updateCursor,1,"#f00");if(l)console.log.apply(undefined,l);
+ updateCursor: function updateCursor() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(updateCursor,1,"#f00");if(l)console.log.apply(undefined,l);
- $("#finger").removeClass("move draw configure");
- switch(me.Crsr.state) {
- case "move": $("#finger").addClass("move"); break;
- case "draw": $("#finger").addClass("draw"); break;
- case "configure": $("#finger").addClass("configure"); break;
- }
- },
+ $("#finger").removeClass("move draw configure");
+ switch(me.Crsr.state) {
+ case "move": $("#finger").addClass("move"); break;
+ case "draw": $("#finger").addClass("draw"); break;
+ case "configure": $("#finger").addClass("configure"); break;
+ }
+ },
/**
* @function mousedown
*/
- mousedown: function mousedown(e) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(mousedown,0,"#f00");if(l)console.log.apply(undefined,l);
-
- e.preventDefault();
+ mousedown: function mousedown(e) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(mousedown,0,"#f00");if(l)console.log.apply(undefined,l);
+
+ e.preventDefault();
- var W=parseFloat($('#atlasMaker canvas').css('width'));
- var H=parseFloat($('#atlasMaker canvas').css('height'));
- var w=parseFloat($('#atlasMaker canvas').attr('width'));
- var h=parseFloat($('#atlasMaker canvas').attr('height'));
- var o=$('#atlasMaker canvas').offset();
- var x=parseInt((e.pageX-o.left)*(w/W));
- // i have to add here the compensation for rectangular pixels: f(brain_Wdim, brain_Hdim)
- var y=parseInt((e.pageY-o.top)*(h/H));
- me.down(x,Math.round(y*me.brain_Wdim/me.brain_Hdim));
- },
+ var W=parseFloat($('#atlasMaker canvas').css('width'));
+ var H=parseFloat($('#atlasMaker canvas').css('height'));
+ var w=parseFloat($('#atlasMaker canvas').attr('width'));
+ var h=parseFloat($('#atlasMaker canvas').attr('height'));
+ var o=$('#atlasMaker canvas').offset();
+ var x=parseInt((e.pageX-o.left)*(w/W));
+ // i have to add here the compensation for rectangular pixels: f(brain_Wdim, brain_Hdim)
+ var y=parseInt((e.pageY-o.top)*(h/H));
+ me.down(x,Math.round(y*me.brain_Wdim/me.brain_Hdim));
+ },
/**
* @function mousemove
* @desc Handles a mouse move event. The x and y slice screens are computed from the pageX and pageY screen coordinates and dispatched to the generic move handler. The position and size of the cursor are adjusted.
* @param {Event} e Event object
*/
- mousemove: function mousemove(e) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(mousemove,2,"#f00");if(l)console.log.apply(undefined,l);
-
- e.preventDefault();
- var W=parseFloat($('#atlasMaker canvas').css('width'));
- var H=parseFloat($('#atlasMaker canvas').css('height'));
- var w=parseFloat($('#atlasMaker canvas').attr('width'));
- var h=parseFloat($('#atlasMaker canvas').attr('height'));
- var o=$('#atlasMaker canvas').offset();
- var x=parseInt((e.pageX-o.left)*(w/W));
- var y=parseInt((e.pageY-o.top)*(h/H));
-
- $("#cursor").css({
- left:(x*(W/w))+'px',
- top:(y*(H/h))+'px',
- width:me.User.penSize*(W/w),
- height:me.User.penSize*(H/h)
- });
- me.move(x,Math.round(y*me.brain_Wdim/me.brain_Hdim));
- },
+ mousemove: function mousemove(e) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(mousemove,2,"#f00");if(l)console.log.apply(undefined,l);
+
+ e.preventDefault();
+ var W=parseFloat($('#atlasMaker canvas').css('width'));
+ var H=parseFloat($('#atlasMaker canvas').css('height'));
+ var w=parseFloat($('#atlasMaker canvas').attr('width'));
+ var h=parseFloat($('#atlasMaker canvas').attr('height'));
+ var o=$('#atlasMaker canvas').offset();
+ var x=parseInt((e.pageX-o.left)*(w/W));
+ var y=parseInt((e.pageY-o.top)*(h/H));
+
+ $("#cursor").css({
+ left:(x*(W/w))+'px',
+ top:(y*(H/h))+'px',
+ width:me.User.penSize*(W/w),
+ height:me.User.penSize*(H/h)
+ });
+ me.move(x,Math.round(y*me.brain_Wdim/me.brain_Hdim));
+ },
/**
* @function mouseup
*/
- mouseup: function mouseup(e) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(mouseup,0,"#f00");if(l)console.log.apply(undefined,l);
-
- me.up(e);
- },
+ mouseup: function mouseup(e) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(mouseup,0,"#f00");if(l)console.log.apply(undefined,l);
+
+ me.up(e);
+ },
/**
* @function touchstart
*/
- touchstart: function touchstart(e) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(touchstart,0,"#f00");if(l)console.log.apply(undefined,l);
-
- e.preventDefault();
+ touchstart: function touchstart(e) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(touchstart,0,"#f00");if(l)console.log.apply(undefined,l);
+
+ e.preventDefault();
- var W=parseFloat($('#atlasMaker canvas').css('width'));
- var H=parseFloat($('#atlasMaker canvas').css('height'));
- var w=parseFloat($('#atlasMaker canvas').attr('width'));
- var h=parseFloat($('#atlasMaker canvas').attr('height'));
- var o=$('#atlasMaker canvas').offset();
- var touchEvent;
- if(e.originalEvent)
- touchEvent=e.originalEvent.changedTouches[0];
- else
- touchEvent=e.changedTouches[0];
- var x=parseInt((touchEvent.pageX-o.left)*(w/W));
- var y=parseInt((touchEvent.pageY-o.top)*(h/H));
-
- if(me.flagUsePreciseCursor) {
- // Precision cursor
- me.Crsr.x0=x;
- me.Crsr.cachedX=x;
- me.Crsr.y0=y;
- me.Crsr.cachedY=y;
- me.Crsr.fx=$("#finger").offset().left;
- me.Crsr.fy=$("#finger").offset().top;
- me.Crsr.touchStarted=true;
- setTimeout(function() {
- if( me.Crsr.cachedX == me.Crsr.x0 && me.Crsr.cachedY==me.Crsr.y0 && !me.Crsr.touchStarted) {
- // short tap: change mode
- me.Crsr.state=(me.Crsr.state=="move")?"draw":"move";
- me.updateCursor();
- }
- },200);
- setTimeout(function() {
- if (me.Crsr.cachedX==me.Crsr.x0 && me.Crsr.cachedY==me.Crsr.y0 && me.Crsr.touchStarted) {
- // long tap: change to configure mode
- me.Crsr.prevState=me.Crsr.state;
- me.Crsr.state="configure";
- me.updateCursor();
- }
- },1000);
- me.down(me.Crsr.x,Math.round(me.Crsr.y*me.brain_Wdim/me.brain_Hdim));
- } else
- me.down(x,Math.round(y*me.brain_Wdim/me.brain_Hdim));
- },
+ var W=parseFloat($('#atlasMaker canvas').css('width'));
+ var H=parseFloat($('#atlasMaker canvas').css('height'));
+ var w=parseFloat($('#atlasMaker canvas').attr('width'));
+ var h=parseFloat($('#atlasMaker canvas').attr('height'));
+ var o=$('#atlasMaker canvas').offset();
+ var touchEvent;
+ if(e.originalEvent)
+ touchEvent=e.originalEvent.changedTouches[0];
+ else
+ touchEvent=e.changedTouches[0];
+ var x=parseInt((touchEvent.pageX-o.left)*(w/W));
+ var y=parseInt((touchEvent.pageY-o.top)*(h/H));
+
+ if(me.flagUsePreciseCursor) {
+ // Precision cursor
+ me.Crsr.x0=x;
+ me.Crsr.cachedX=x;
+ me.Crsr.y0=y;
+ me.Crsr.cachedY=y;
+ me.Crsr.fx=$("#finger").offset().left;
+ me.Crsr.fy=$("#finger").offset().top;
+ me.Crsr.touchStarted=true;
+ setTimeout(function() {
+ if( me.Crsr.cachedX == me.Crsr.x0 && me.Crsr.cachedY==me.Crsr.y0 && !me.Crsr.touchStarted) {
+ // short tap: change mode
+ me.Crsr.state=(me.Crsr.state=="move")?"draw":"move";
+ me.updateCursor();
+ }
+ },200);
+ setTimeout(function() {
+ if (me.Crsr.cachedX==me.Crsr.x0 && me.Crsr.cachedY==me.Crsr.y0 && me.Crsr.touchStarted) {
+ // long tap: change to configure mode
+ me.Crsr.prevState=me.Crsr.state;
+ me.Crsr.state="configure";
+ me.updateCursor();
+ }
+ },1000);
+ me.down(me.Crsr.x,Math.round(me.Crsr.y*me.brain_Wdim/me.brain_Hdim));
+ } else
+ me.down(x,Math.round(y*me.brain_Wdim/me.brain_Hdim));
+ },
/**
* @function touchmove
*/
- touchmove: function touchmove(e) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(touchmove,2,"#f00");if(l)console.log.apply(undefined,l);
-
- if(me.Crsr.touchStarted==false && me.debug) {
- console.log("WARNING: touch can move without having started");
- }
-
- e.preventDefault();
+ touchmove: function touchmove(e) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(touchmove,2,"#f00");if(l)console.log.apply(undefined,l);
+
+ if(me.Crsr.touchStarted==false && me.debug) {
+ console.log("WARNING: touch can move without having started");
+ }
+
+ e.preventDefault();
- var W=parseFloat($('#atlasMaker canvas').css('width'));
- var H=parseFloat($('#atlasMaker canvas').css('height'));
- var w=parseFloat($('#atlasMaker canvas').attr('width'));
- var h=parseFloat($('#atlasMaker canvas').attr('height'));
- var o=$('#atlasMaker canvas').offset();
- var touchEvent;
- if(e.originalEvent)
- touchEvent=e.originalEvent.changedTouches[0];
- else
- touchEvent=e.changedTouches[0];
- var x=parseInt((touchEvent.pageX-o.left)*(w/W));
- var y=parseInt((touchEvent.pageY-o.top)*(h/H));
-
- if(me.flagUsePreciseCursor) {
- // Precision cursor
- var dx=x-me.Crsr.x0;
- var dy=y-me.Crsr.y0;
- if(me.Crsr.state=="move"||me.Crsr.state=="draw") {
- me.Crsr.x+=dx;
- me.Crsr.y+=dy;
- $("#cursor").css({left:me.Crsr.x*(W/w),top:me.Crsr.y*(H/h),width:me.User.penSize*(W/w),height:me.User.penSize*(H/h)});
- if(me.Crsr.state=="draw")
- me.move(me.Crsr.x,Math.round(me.Crsr.y*me.brain_Wdim/me.brain_Hdim));
- }
- me.Crsr.fx+=dx*(W/w);
- me.Crsr.fy+=dy*(H/h);
- $("#finger").offset({left:me.Crsr.fx,top:me.Crsr.fy});
-
- me.Crsr.x0=x;
- me.Crsr.y0=y;
- } else {
- $("#cursor").css({
- left:(x*(W/w))+'px',
- top:(y*(H/h))+'px',
- width:me.User.penSize*(W/w),
- height:me.User.penSize*(H/h)
- });
- me.move(x,Math.round(y*me.brain_Wdim/me.brain_Hdim));
- }
- },
+ var W=parseFloat($('#atlasMaker canvas').css('width'));
+ var H=parseFloat($('#atlasMaker canvas').css('height'));
+ var w=parseFloat($('#atlasMaker canvas').attr('width'));
+ var h=parseFloat($('#atlasMaker canvas').attr('height'));
+ var o=$('#atlasMaker canvas').offset();
+ var touchEvent;
+ if(e.originalEvent)
+ touchEvent=e.originalEvent.changedTouches[0];
+ else
+ touchEvent=e.changedTouches[0];
+ var x=parseInt((touchEvent.pageX-o.left)*(w/W));
+ var y=parseInt((touchEvent.pageY-o.top)*(h/H));
+
+ if(me.flagUsePreciseCursor) {
+ // Precision cursor
+ var dx=x-me.Crsr.x0;
+ var dy=y-me.Crsr.y0;
+ if(me.Crsr.state=="move"||me.Crsr.state=="draw") {
+ me.Crsr.x+=dx;
+ me.Crsr.y+=dy;
+ $("#cursor").css({left:me.Crsr.x*(W/w),top:me.Crsr.y*(H/h),width:me.User.penSize*(W/w),height:me.User.penSize*(H/h)});
+ if(me.Crsr.state=="draw")
+ me.move(me.Crsr.x,Math.round(me.Crsr.y*me.brain_Wdim/me.brain_Hdim));
+ }
+ me.Crsr.fx+=dx*(W/w);
+ me.Crsr.fy+=dy*(H/h);
+ $("#finger").offset({left:me.Crsr.fx,top:me.Crsr.fy});
+
+ me.Crsr.x0=x;
+ me.Crsr.y0=y;
+ } else {
+ $("#cursor").css({
+ left:(x*(W/w))+'px',
+ top:(y*(H/h))+'px',
+ width:me.User.penSize*(W/w),
+ height:me.User.penSize*(H/h)
+ });
+ me.move(x,Math.round(y*me.brain_Wdim/me.brain_Hdim));
+ }
+ },
/**
* @function touchend
*/
- touchend: function touchend(e) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(touchend,0,"#f00");if(l)console.log.apply(undefined,l);
-
- e.preventDefault();
-
- if(me.flagUsePreciseCursor) {
- // Precision cursor
- me.Crsr.touchStarted=false;
- if(me.Crsr.state=="configure") {
- me.Crsr.state=me.Crsr.prevState;
- me.updateCursor();
- }
- }
- me.up(e);
- },
+ touchend: function touchend(e) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(touchend,0,"#f00");if(l)console.log.apply(undefined,l);
+
+ e.preventDefault();
+
+ if(me.flagUsePreciseCursor) {
+ // Precision cursor
+ me.Crsr.touchStarted=false;
+ if(me.Crsr.state=="configure") {
+ me.Crsr.state=me.Crsr.prevState;
+ me.updateCursor();
+ }
+ }
+ me.up(e);
+ },
/**
* @function down
* @desc Generic pointer down event: Deals with down events generated by mouse clicks or touch events. The effect of the down event is determined by the current User.tool
* @param {integer} x X coordinate in slice space
* @param {integer} y Y coordinate in slice space
*/
- down: function down(x,y) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(down,0,"#f00");if(l)console.log.apply(undefined,l);
-
- var z=me.User.slice;
-
- switch(me.User.tool) {
- case 'show':
+ down: function down(x,y) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(down,0,"#f00");if(l)console.log.apply(undefined,l);
+
+ var z=me.User.slice;
+
+ switch(me.User.tool) {
+ case 'show':
me.User.mouseIsDown = true;
me.sendUserDataMessage(JSON.stringify({'mouseIsDown':true}));
me.showxy(-1,'m',x,y,me.User);
- break;
- case 'paint':
- // check for 'edit' access
- if(me.editMode == 0)
- return;
- // fill
- if(me.User.doFill)
- me.paintxy(-1,'f',x,y,me.User);
- //paint
- else {
- me.User.mouseIsDown = true;
- me.sendUserDataMessage(JSON.stringify({'mouseIsDown':true}));
- me.paintxy(-1,'mf',x,y,me.User);
- }
- break;
- case 'erase':
- // check for 'edit' access
- if(me.editMode == 0)
- return;
- // fill
- if(me.User.doFill)
- me.paintxy(-1,'e',x,y,me.User);
+ break;
+ case 'paint':
+ // check for 'edit' access
+ if(me.editMode == 0)
+ return;
+ // fill
+ if(me.User.doFill)
+ me.paintxy(-1,'f',x,y,me.User);
+ //paint
+ else {
+ me.User.mouseIsDown = true;
+ me.sendUserDataMessage(JSON.stringify({'mouseIsDown':true}));
+ me.paintxy(-1,'mf',x,y,me.User);
+ }
+ break;
+ case 'erase':
+ // check for 'edit' access
+ if(me.editMode == 0)
+ return;
+ // fill
+ if(me.User.doFill)
+ me.paintxy(-1,'e',x,y,me.User);
// erase
- else {
- me.User.mouseIsDown = true;
- me.sendUserDataMessage(JSON.stringify({'mouseIsDown':true}));
- me.paintxy(-1,'me',x,y,me.User);
- }
- break;
- case 'measure':
- if(me.User.measureLength==null)
- me.User.measureLength=[{x:x,y:y}];
- else
- me.User.measureLength.push({x:x,y:y});
- break;
- case 'adjust':
- me.User.mouseIsDown = true;
- me.info.x=x/me.brain_W;
- me.info.y=1-y/me.brain_H;
- break;
- case 'eyedrop':
- var value = me.eyedrop( x,y,me.User );
- var index = me.ontology.valueToIndex[ value ];
- var selRegionName = me.ontology.labels[ index ].name;
- me.info.region = selRegionName;
- me.changePenColor( index );
- var selRegionColor = me.ontology.labels[ index ].color;
- break;
- }
-
- // init annotation length counter
- me.annotationLength=0;
- },
+ else {
+ me.User.mouseIsDown = true;
+ me.sendUserDataMessage(JSON.stringify({'mouseIsDown':true}));
+ me.paintxy(-1,'me',x,y,me.User);
+ }
+ break;
+ case 'measure':
+ if(me.User.measureLength==null)
+ me.User.measureLength=[{x:x,y:y}];
+ else
+ me.User.measureLength.push({x:x,y:y});
+ break;
+ case 'adjust':
+ me.User.mouseIsDown = true;
+ me.info.x=x/me.brain_W;
+ me.info.y=1-y/me.brain_H;
+ break;
+ case 'eyedrop':
+ var value = me.eyedrop( x,y,me.User );
+ var index = me.ontology.valueToIndex[ value ];
+ var selRegionName = me.ontology.labels[ index ].name;
+ me.info.region = selRegionName;
+ me.changePenColor( index );
+ var selRegionColor = me.ontology.labels[ index ].color;
+ break;
+ }
+
+ // init annotation length counter
+ me.annotationLength=0;
+ },
/**
* @function move
* @desc Generic pointer move event: Deals with move events generated by mouse clicks or touch events. The effect of the move event is determined by the current User.tool
* @param {integer} x X coordinate in slice space
* @param {integer} y Y coordinate in slice space
*/
- move: function move(x,y) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(move,2,"#f00");if(l)console.log.apply(undefined,l);
-
- /*
- if(MyLoginWidget.loggedin==0 || me.editMode==0)
- return;
- */
+ move: function move(x,y) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(move,2,"#f00");if(l)console.log.apply(undefined,l);
+
+ /*
+ if(MyLoginWidget.loggedin==0 || me.editMode==0)
+ return;
+ */
- var z=me.User.slice;
+ var z=me.User.slice;
- if(!me.User.mouseIsDown)
- return;
-
- switch(me.User.tool) {
- case 'show':
- me.showxy(-1,'m',x,y,me.User);
- break;
- case 'paint':
- me.paintxy(-1,'lf',x,y,me.User);
- break;
- case 'erase':
- me.paintxy(-1,'le',x,y,me.User);
- break;
- case 'adjust':
- me.info.x=x/me.brain_W;
- me.info.y=1-y/me.brain_H;
- me.drawImages();
- break;
- }
- },
+ if(!me.User.mouseIsDown)
+ return;
+
+ switch(me.User.tool) {
+ case 'show':
+ me.showxy(-1,'m',x,y,me.User);
+ break;
+ case 'paint':
+ me.paintxy(-1,'lf',x,y,me.User);
+ break;
+ case 'erase':
+ me.paintxy(-1,'le',x,y,me.User);
+ break;
+ case 'adjust':
+ me.info.x=x/me.brain_W;
+ me.info.y=1-y/me.brain_H;
+ me.drawImages();
+ break;
+ }
+ },
/**
* @function up
* @desc Generic pointer up event: Deals with up events generated by mouse clicks or touch events.
* @param {integer} x X coordinate in slice space
* @param {integer} y Y coordinate in slice space
*/
- up: function up(e) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(up,0,"#f00");if(l)console.log.apply(undefined,l);
+ up: function up(e) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(up,0,"#f00");if(l)console.log.apply(undefined,l);
- /*
- if(MyLoginWidget.loggedin==0 || me.editMode==0)
- return;
- */
+ /*
+ if(MyLoginWidget.loggedin==0 || me.editMode==0)
+ return;
+ */
- // Send mouse up (touch ended) message
- me.User.mouseIsDown = false;
- me.User.x0=-1;
+ // Send mouse up (touch ended) message
+ me.User.mouseIsDown = false;
+ me.User.x0=-1;
me.sendUserDataMessage(JSON.stringify({'mouseIsDown':false}));
-
- var msg;
-
- switch(me.User.tool) {
- case 'show':
+
+ var msg;
+ switch(me.User.tool) {
+ case 'show':
var msg={"c":"u"};
me.sendShowMessage(msg);
break;
@@ -761,7 +760,7 @@ var AtlasMakerInteraction = {
case 'erase':
var msg={c:"mu"};
me.sendPaintMessage(msg);
-
+
// add annotated length to User.annotation length and post to DB
me.logToDatabase("annotationLength",{
source:me.User.source,
@@ -773,78 +772,72 @@ var AtlasMakerInteraction = {
me.info.length = length+" mm";
me.displayInformation();
});
-
+
me.annotationLength=0;
-
+
// compute total segmented volume
var vol=me.computeSegmentedVolume();
me.info.volume=parseInt(vol)+" mm3";
break;
- case 'eyedrop':
- me.displayInformation();
-
- var msg={"c":"mu"};
- me.sendPaintMessage(msg);
- break;
default:
var msg={"c":"mu"};
me.sendPaintMessage(msg);
}
-
- /*
- TEST
- */
- //me.sendRequestSliceMessage();
- },
+
+ /*
+ TEST
+ */
+ //me.sendRequestSliceMessage();
+ },
/**
* @function keyDown
*/
- keyDown: function keyDown(e) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(keyDown,2,"#f00");if(l)console.log.apply(undefined,l);
-
- // console.log("key:",e.which);
-
- if(e.which==13 && $(e.target).attr('contenteditable')) {
+ keyDown: function keyDown(e) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(keyDown,2,"#f00");if(l)console.log.apply(undefined,l);
+
+ // console.log("key:",e.which);
+
+ if(e.which==13 && $(e.target).attr('contenteditable')) {
e.preventDefault();
return;
}
-
- if(e.target.tagName!="BODY")
- return;
-
- switch(e.which) {
- case 13: // return
- if(me.User.measureLength) {
- var length=0;
- var p=me.User.measureLength;
- var wdim=me.brain_Wdim,hdim=me.brain_Hdim;
- var i;
- for(i=1;i
");
- me.User.measureLength=null;
- }
- break;
- case 37: // left arrow
- me.prevSlice();
- e.preventDefault();
- break;
- case 39: // right arrow
- me.nextSlice(this);
- e.preventDefault();
- break;
- }
- },
+
+ if(e.target.tagName!="BODY")
+ return;
+
+ switch(e.which) {
+ case 13: // return
+ if(me.User.measureLength) {
+ var length=0;
+ var p=me.User.measureLength;
+ var wdim=me.brain_Wdim,hdim=me.brain_Hdim;
+ var i;
+ for(i=1;i
");
+ me.User.measureLength=null;
+ }
+ break;
+ case 37: // left arrow
+ me.prevSlice();
+ e.preventDefault();
+ break;
+ case 39: // right arrow
+ me.nextSlice(this);
+ e.preventDefault();
+ break;
+ }
+ },
/**
* @function onkey
*/
- onkey: function onkey(e) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(onkey,2,"#f00");if(l)console.log.apply(undefined,l);
-
- if (e.keyCode == 13) {
- me.sendChatMessage();
- }
- }
-}
+ onkey: function onkey(e) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(onkey,2,"#f00");if(l)console.log.apply(undefined,l);
+
+ if (e.keyCode == 13) {
+ me.sendChatMessage();
+ }
+ }
+}
\ No newline at end of file
diff --git a/public/js/atlasMaker-io.js b/public/js/atlasMaker-io.js
index 78c36124..b93c08fa 100644
--- a/public/js/atlasMaker-io.js
+++ b/public/js/atlasMaker-io.js
@@ -15,37 +15,37 @@ var AtlasMakerIO = {
.floatle('intent_p2') // 2nd intent parameter.
.floatle('intent_p3') // 3rd intent parameter.
.word16Sle('intent_code') // nifti intent.
- .word16Sle('datatype') // Data type.
- .word16Sle('bitpix') // Number of bits per voxel.
- .word16Sle('slice_start') // First slice index.
+ .word16Sle('datatype') // Data type.
+ .word16Sle('bitpix') // Number of bits per voxel.
+ .word16Sle('slice_start') // First slice index.
.array('pixdim',8,'floatle') // Grid spacings (unit per dimension).
- .floatle('vox_offset') // Offset into a .nii file.
- .floatle('scl_slope') // Data scaling, slope.
- .floatle('scl_inter') // Data scaling, offset.
- .word16Sle('slice_end') // Last slice index.
- .word8('slice_code') // Slice timing order.
- .word8('xyzt_units') // Units of pixdim[1..4].
- .floatle('cal_max') // Maximum display intensity.
- .floatle('cal_min') // Minimum display intensity.
- .floatle('slice_duration') // Time for one slice.
- .floatle('toffset') // Time axis shift.
- .word32Sle('glmax') // Not used; compatibility with analyze.
- .word32Sle('glmin') // Not used; compatibility with analyze.
- .chars('descrip',80) // Any text.
- .chars('aux_file',24) // Auxiliary filename.
- .word16Sle('qform_code') // Use the quaternion fields.
- .word16Sle('sform_code') // Use of the affine fields.
- .floatle('quatern_b') // Quaternion b parameter.
- .floatle('quatern_c') // Quaternion c parameter.
- .floatle('quatern_d') // Quaternion d parameter.
- .floatle('qoffset_x') // Quaternion x shift.
- .floatle('qoffset_y') // Quaternion y shift.
- .floatle('qoffset_z') // Quaternion z shift.
+ .floatle('vox_offset') // Offset into a .nii file.
+ .floatle('scl_slope') // Data scaling, slope.
+ .floatle('scl_inter') // Data scaling, offset.
+ .word16Sle('slice_end') // Last slice index.
+ .word8('slice_code') // Slice timing order.
+ .word8('xyzt_units') // Units of pixdim[1..4].
+ .floatle('cal_max') // Maximum display intensity.
+ .floatle('cal_min') // Minimum display intensity.
+ .floatle('slice_duration') // Time for one slice.
+ .floatle('toffset') // Time axis shift.
+ .word32Sle('glmax') // Not used; compatibility with analyze.
+ .word32Sle('glmin') // Not used; compatibility with analyze.
+ .chars('descrip',80) // Any text.
+ .chars('aux_file',24) // Auxiliary filename.
+ .word16Sle('qform_code') // Use the quaternion fields.
+ .word16Sle('sform_code') // Use of the affine fields.
+ .floatle('quatern_b') // Quaternion b parameter.
+ .floatle('quatern_c') // Quaternion c parameter.
+ .floatle('quatern_d') // Quaternion d parameter.
+ .floatle('qoffset_x') // Quaternion x shift.
+ .floatle('qoffset_y') // Quaternion y shift.
+ .floatle('qoffset_z') // Quaternion z shift.
.array('srow_x',4,'floatle') // 1st row affine transform
.array('srow_y',4,'floatle') // 2nd row affine transform.
.array('srow_z',4,'floatle') // 3rd row affine transform.
- .chars('intent_name',16) // Name or meaning of the data.
- .chars('magic',4), // Magic string.
+ .chars('intent_name',16) // Name or meaning of the data.
+ .chars('magic',4), // Magic string.
NiiHdrBE: Struct()
.word32Sbe('sizeof_hdr') // Size of the header. Must be 348 (bytes)
.chars('data_type',10) // Not used; compatibility with analyze.
@@ -59,37 +59,37 @@ var AtlasMakerIO = {
.floatbe('intent_p2') // 2nd intent parameter.
.floatbe('intent_p3') // 3rd intent parameter.
.word16Sbe('intent_code') // nifti intent.
- .word16Sbe('datatype') // Data type.
- .word16Sbe('bitpix') // Number of bits per voxel.
- .word16Sbe('slice_start') // First slice index.
+ .word16Sbe('datatype') // Data type.
+ .word16Sbe('bitpix') // Number of bits per voxel.
+ .word16Sbe('slice_start') // First slice index.
.array('pixdim',8,'floatbe') // Grid spacings (unit per dimension).
- .floatbe('vox_offset') // Offset into a .nii file.
- .floatbe('scl_slope') // Data scaling, slope.
- .floatbe('scl_inter') // Data scaling, offset.
- .word16Sbe('slice_end') // Last slice index.
- .word8('slice_code') // Slice timing order.
- .word8('xyzt_units') // Units of pixdim[1..4].
- .floatbe('cal_max') // Maximum display intensity.
- .floatbe('cal_min') // Minimum display intensity.
- .floatbe('slice_duration') // Time for one slice.
- .floatbe('toffset') // Time axis shift.
- .word32Sbe('glmax') // Not used; compatibility with analyze.
- .word32Sbe('glmin') // Not used; compatibility with analyze.
- .chars('descrip',80) // Any text.
- .chars('aux_file',24) // Auxiliary filename.
- .word16Sbe('qform_code') // Use the quaternion fields.
- .word16Sbe('sform_code') // Use of the affine fields.
- .floatbe('quatern_b') // Quaternion b parameter.
- .floatbe('quatern_c') // Quaternion c parameter.
- .floatbe('quatern_d') // Quaternion d parameter.
- .floatbe('qoffset_x') // Quaternion x shift.
- .floatbe('qoffset_y') // Quaternion y shift.
- .floatbe('qoffset_z') // Quaternion z shift.
+ .floatbe('vox_offset') // Offset into a .nii file.
+ .floatbe('scl_slope') // Data scaling, slope.
+ .floatbe('scl_inter') // Data scaling, offset.
+ .word16Sbe('slice_end') // Last slice index.
+ .word8('slice_code') // Slice timing order.
+ .word8('xyzt_units') // Units of pixdim[1..4].
+ .floatbe('cal_max') // Maximum display intensity.
+ .floatbe('cal_min') // Minimum display intensity.
+ .floatbe('slice_duration') // Time for one slice.
+ .floatbe('toffset') // Time axis shift.
+ .word32Sbe('glmax') // Not used; compatibility with analyze.
+ .word32Sbe('glmin') // Not used; compatibility with analyze.
+ .chars('descrip',80) // Any text.
+ .chars('aux_file',24) // Auxiliary filename.
+ .word16Sbe('qform_code') // Use the quaternion fields.
+ .word16Sbe('sform_code') // Use of the affine fields.
+ .floatbe('quatern_b') // Quaternion b parameter.
+ .floatbe('quatern_c') // Quaternion c parameter.
+ .floatbe('quatern_d') // Quaternion d parameter.
+ .floatbe('qoffset_x') // Quaternion x shift.
+ .floatbe('qoffset_y') // Quaternion y shift.
+ .floatbe('qoffset_z') // Quaternion z shift.
.array('srow_x',4,'floatbe') // 1st row affine transform
.array('srow_y',4,'floatbe') // 2nd row affine transform.
.array('srow_z',4,'floatbe') // 3rd row affine transform.
- .chars('intent_name',16) // Name or meaning of the data.
- .chars('magic',4), // Magic string.
+ .chars('intent_name',16) // Name or meaning of the data.
+ .chars('magic',4), // Magic string.
MghHdr: Struct()
.word32Sbe('v')
.word32Sbe('ndim1')
@@ -107,17 +107,17 @@ var AtlasMakerIO = {
/**
* @function encodeNifti
*/
- encodeNifti: function encodeNifti() {
- var me=AtlasMakerWidget;
- var l=me.traceLog(encodeNifti);if(l)console.log.apply(undefined,l);
+ encodeNifti: function encodeNifti() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(encodeNifti);if(l)console.log.apply(undefined,l);
- var sizeof_hdr=348;
- var dimensions=4; // number of dimension values provided
- var spacetimeunits=2+8; // 2=nifti code for millimetres | 8=nifti code for seconds
- var datatype=2; // datatype for 8 bits (DT_UCHAR8 in nifti or UCHAR in analyze)
- var vox_offset=352;
- var bitsPerVoxel=8;
-
+ var sizeof_hdr=348;
+ var dimensions=4; // number of dimension values provided
+ var spacetimeunits=2+8; // 2=nifti code for millimetres | 8=nifti code for seconds
+ var datatype=2; // datatype for 8 bits (DT_UCHAR8 in nifti or UCHAR in analyze)
+ var vox_offset=352;
+ var bitsPerVoxel=8;
+
var newHdr = {
sizeof_hdr: sizeof_hdr,
data_type: '', db_name: '', extents: 0, session_error: 0, regular: 0, dim_info: 0,
@@ -128,7 +128,7 @@ var AtlasMakerIO = {
slice_start: 0,
pixdim: [-1, me.User.pixdim[0], me.User.pixdim[1], me.User.pixdim[2], 0, 1, 1, 1],
vox_offset: vox_offset,
- scl_slope: 1, scl_inter: 0, slice_end: 0, slice_code: 0,
+ scl_slope: 0, scl_inter: 0, slice_end: 0, slice_code: 0,
xyzt_units: 10,
cal_max: 0, cal_min: 0, slice_duration: 0, toffset: 0,
glmax: 0, glmin: 0,
@@ -149,66 +149,66 @@ var AtlasMakerIO = {
for(i in newHdr)
me.NiiHdrLE.fields[i] = newHdr[i];
hdr = toArrayBuffer(niihdr);
- var data=me.atlas.data;
+ var data=me.atlas.data;
var nii = new Uint8Array(vox_offset+data.length);
for(i=0;i
Math.abs(mi.v)) mi={i:n,v:o}});
var mj={i:0,v:0};j.map(function(o,n){if(Math.abs(o)>Math.abs(mj.v)) mj={i:n,v:o}});
var mk={i:0,v:0};k.map(function(o,n){if(Math.abs(o)>Math.abs(mk.v)) mk={i:n,v:o}});
- mri.s2v = {
- // old s2v fields
- s2w: me.invMat(w2s),
- sdim: [],
- sori: [-wmin[0]/Math.abs(wpixdim[0]),-wmin[1]/Math.abs(wpixdim[1]),-wmin[2]/Math.abs(wpixdim[2])],
- wpixdim: [],
- w2v: me.invMat(v2w),
+ mri.s2v = {
+ // old s2v fields
+ s2w: me.invMat(w2s),
+ sdim: [],
+ sori: [-wmin[0]/Math.abs(wpixdim[0]),-wmin[1]/Math.abs(wpixdim[1]),-wmin[2]/Math.abs(wpixdim[2])],
+ wpixdim: [],
+ w2v: me.invMat(v2w),
wori: wori,
// new s2v transformation
@@ -317,7 +317,7 @@ var AtlasMakerIO = {
X: (mi.v>0)?0:(mri.dim[0]-1), // starting value for space coordinate x when voxel coordinate i starts
Y: (mj.v>0)?0:(mri.dim[1]-1), // same for y
Z: (mk.v>0)?0:(mri.dim[2]-1) // same for z
- };
+ };
mri.v2w=v2w;
mri.wori=wori;
mri.s2v.sdim[mi.i] = mri.dim[0];
@@ -326,119 +326,119 @@ var AtlasMakerIO = {
mri.s2v.wpixdim[mi.i] = mri.pixdim[0];
mri.s2v.wpixdim[mj.i] = mri.pixdim[1];
mri.s2v.wpixdim[mk.i] = mri.pixdim[2];
- },
+ },
/**
* @function testS2VTransformation
*/
- testS2VTransformation: function testS2VTransformation() {
- var me=AtlasMakerWidget;
- var l=me.traceLog(testS2VTransformation);if(l)console.log.apply(undefined,l);
-
- /*
- check the S2V transformation to see if it looks correct.
- If it does not, reset it
- */
- var mri=me.User; // this line is different from server
- var doReset=false;
-
- // console.log("Transformation TEST:");
- // console.log(" 1. transformation volume");
-
- var vv=mri.dim[0]*mri.dim[1]*mri.dim[2];
- var vs=mri.s2v.sdim[0]*mri.s2v.sdim[1]*mri.s2v.sdim[2];
- var diff=(vs-vv)/vv;
- if(Math.abs(diff)>0.001) {
- console.log(" ERROR: Difference is too large");
- console.log(" original volume:",vv);
- console.log(" rotated volume:",vs);
- console.log(" % difference:",diff*100);
- doReset=true;
- } else {
- // console.log(" ok.");
- }
-
- // console.log(" 2. transformation origin");
- if( mri.s2v.sori[0]<0||mri.s2v.sori[0]>mri.s2v.sdim[0] ||
- mri.s2v.sori[1]<0||mri.s2v.sori[1]>mri.s2v.sdim[1] ||
- mri.s2v.sori[2]<0||mri.s2v.sori[2]>mri.s2v.sdim[2]) {
- // console.log(" Origin point is outside the dimensions of the data");
- doReset=true;
- } else {
- // console.log(" ok.");
- }
+ testS2VTransformation: function testS2VTransformation() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(testS2VTransformation);if(l)console.log.apply(undefined,l);
+
+ /*
+ check the S2V transformation to see if it looks correct.
+ If it does not, reset it
+ */
+ var mri=me.User; // this line is different from server
+ var doReset=false;
+
+ // console.log("Transformation TEST:");
+ // console.log(" 1. transformation volume");
+
+ var vv=mri.dim[0]*mri.dim[1]*mri.dim[2];
+ var vs=mri.s2v.sdim[0]*mri.s2v.sdim[1]*mri.s2v.sdim[2];
+ var diff=(vs-vv)/vv;
+ if(Math.abs(diff)>0.001) {
+ console.log(" ERROR: Difference is too large");
+ console.log(" original volume:",vv);
+ console.log(" rotated volume:",vs);
+ console.log(" % difference:",diff*100);
+ doReset=true;
+ } else {
+ // console.log(" ok.");
+ }
+
+ // console.log(" 2. transformation origin");
+ if( mri.s2v.sori[0]<0||mri.s2v.sori[0]>mri.s2v.sdim[0] ||
+ mri.s2v.sori[1]<0||mri.s2v.sori[1]>mri.s2v.sdim[1] ||
+ mri.s2v.sori[2]<0||mri.s2v.sori[2]>mri.s2v.sdim[2]) {
+ // console.log(" Origin point is outside the dimensions of the data");
+ doReset=true;
+ } else {
+ // console.log(" ok.");
+ }
- if(doReset) {
- // console.log("THE TRANSFORMATION WILL BE RESET");
- mri.v2w=[[mri.pixdim[0],0,0],[0,-mri.pixdim[1],0],[0,0,-mri.pixdim[2]]];
- mri.wori=[0,mri.dim[1]-1,mri.dim[2]-1];
+ if(doReset) {
+ // console.log("THE TRANSFORMATION WILL BE RESET");
+ mri.v2w=[[mri.pixdim[0],0,0],[0,-mri.pixdim[1],0],[0,0,-mri.pixdim[2]]];
+ mri.wori=[0,mri.dim[1]-1,mri.dim[2]-1];
- // re-compute the transformation from voxel space to screen space
- me.computeS2VTransformation(); // this line is different from server
- /*
- console.log(mri.dir);
- console.log(mri.ori);
- console.log(mri.s2v);
- */
- }
- },
+ // re-compute the transformation from voxel space to screen space
+ me.computeS2VTransformation(); // this line is different from server
+ /*
+ console.log(mri.dir);
+ console.log(mri.ori);
+ console.log(mri.s2v);
+ */
+ }
+ },
/**
* @function S2I
*/
- S2I: function S2I(s,mri) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(S2I,3);if(l)console.log.apply(undefined,l);
-
+ S2I: function S2I(s,mri) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(S2I,3);if(l)console.log.apply(undefined,l);
+
var s2v = mri.s2v;
var v = [s2v.X+s2v.dx*s[s2v.x],s2v.Y+s2v.dy*s[s2v.y],s2v.Z+s2v.dz*s[s2v.z]];
index = v[0] + v[1]*mri.dim[0] + v[2]*mri.dim[0]*mri.dim[1];
return index;
- },
+ },
/**
* @function mulMatVec
*/
- mulMatVec: function mulMatVec(m,v) {
- return [
- m[0][0]*v[0]+m[0][1]*v[1]+m[0][2]*v[2],
- m[1][0]*v[0]+m[1][1]*v[1]+m[1][2]*v[2],
- m[2][0]*v[0]+m[2][1]*v[1]+m[2][2]*v[2]
- ];
- },
+ mulMatVec: function mulMatVec(m,v) {
+ return [
+ m[0][0]*v[0]+m[0][1]*v[1]+m[0][2]*v[2],
+ m[1][0]*v[0]+m[1][1]*v[1]+m[1][2]*v[2],
+ m[2][0]*v[0]+m[2][1]*v[1]+m[2][2]*v[2]
+ ];
+ },
/**
* @function invMat
*/
- invMat: function invMat(m) {
- var det;
- var w=[[],[],[]];
+ invMat: function invMat(m) {
+ var det;
+ var w=[[],[],[]];
- det=m[0][1]*m[1][2]*m[2][0] + m[0][2]*m[1][0]*m[2][1] + m[0][0]*m[1][1]*m[2][2] - m[0][2]*m[1][1]*m[2][0] - m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2];
-
- w[0][0]=(m[1][1]*m[2][2] - m[1][2]*m[2][1])/det;
- w[0][1]=(m[0][2]*m[2][1] - m[0][1]*m[2][2])/det;
- w[0][2]=(m[0][1]*m[1][2] - m[0][2]*m[1][1])/det;
-
- w[1][0]=(m[1][2]*m[2][0] - m[1][0]*m[2][2])/det;
- w[1][1]=(m[0][0]*m[2][2] - m[0][2]*m[2][0])/det;
- w[1][2]=(m[0][2]*m[1][0] - m[0][0]*m[1][2])/det;
-
- w[2][0]=(m[1][0]*m[2][1] - m[1][1]*m[2][0])/det;
- w[2][1]=(m[0][1]*m[2][0] - m[0][0]*m[2][1])/det;
- w[2][2]=(m[0][0]*m[1][1] - m[0][1]*m[1][0])/det;
-
- return w;
- },
+ det=m[0][1]*m[1][2]*m[2][0] + m[0][2]*m[1][0]*m[2][1] + m[0][0]*m[1][1]*m[2][2] - m[0][2]*m[1][1]*m[2][0] - m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2];
+
+ w[0][0]=(m[1][1]*m[2][2] - m[1][2]*m[2][1])/det;
+ w[0][1]=(m[0][2]*m[2][1] - m[0][1]*m[2][2])/det;
+ w[0][2]=(m[0][1]*m[1][2] - m[0][2]*m[1][1])/det;
+
+ w[1][0]=(m[1][2]*m[2][0] - m[1][0]*m[2][2])/det;
+ w[1][1]=(m[0][0]*m[2][2] - m[0][2]*m[2][0])/det;
+ w[1][2]=(m[0][2]*m[1][0] - m[0][0]*m[1][2])/det;
+
+ w[2][0]=(m[1][0]*m[2][1] - m[1][1]*m[2][0])/det;
+ w[2][1]=(m[0][1]*m[2][0] - m[0][0]*m[2][1])/det;
+ w[2][2]=(m[0][0]*m[1][1] - m[0][1]*m[1][0])/det;
+
+ return w;
+ },
/**
* @function subVecVec
*/
- subVecVec: function subVecVec(a,b) {
- return [a[0]-b[0],a[1]-b[1],a[2]-b[2]];
- },
+ subVecVec: function subVecVec(a,b) {
+ return [a[0]-b[0],a[1]-b[1],a[2]-b[2]];
+ },
/**
* @function addVecVec
*/
- addVecVec: function addVecVec(a,b) {
- return [a[0]+b[0],a[1]+b[1],a[2]+b[2]];
- },
- /*
- Linear Algebra}
- */
+ addVecVec: function addVecVec(a,b) {
+ return [a[0]+b[0],a[1]+b[1],a[2]+b[2]];
+ },
+ /*
+ Linear Algebra}
+ */
};
\ No newline at end of file
diff --git a/public/js/atlasMaker-paint.js b/public/js/atlasMaker-paint.js
index a8eb34b6..b19ae2af 100644
--- a/public/js/atlasMaker-paint.js
+++ b/public/js/atlasMaker-paint.js
@@ -2,41 +2,41 @@
* @page AtlasMaker: Painting commands
*/
var AtlasMakerPaint = {
- //====================================================================================
- // Paint functions
- //====================================================================================
- showxy: function showxy(u,c,x,y,usr) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(showxy,1,"#0c0");if(l)console.log.apply(undefined,l);
-
- // u: user number
- // c: command
- // x, y: coordinates
- msg={c: c, x: x, y: y};
- if(u==-1 && JSON.stringify(msg)!=JSON.stringify(me.msg0)) {
- me.sendShowMessage(msg);
- me.msg0=msg;
- }
- if(u!=-1) {
- switch(c) {
- case 'u':
- if(usr.pointer) {
+ //====================================================================================
+ // Paint functions
+ //====================================================================================
+ showxy: function showxy(u,c,x,y,usr) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(showxy,1,"#0c0");if(l)console.log.apply(undefined,l);
+
+ // u: user number
+ // c: command
+ // x, y: coordinates
+ msg={c: c, x: x, y: y};
+ if(u==-1 && JSON.stringify(msg)!=JSON.stringify(me.msg0)) {
+ me.sendShowMessage(msg);
+ me.msg0=msg;
+ }
+ if(u!=-1) {
+ switch(c) {
+ case 'u':
+ if(usr.pointer) {
usr.pointer.remove();
delete usr.pointer;
}
- break;
- case 'm':
+ break;
+ case 'm':
if(!usr.pointer) {
usr.pointer = $(''+((usr.username == 'Anonymous')?u:usr.username)+'
');
$("#resizable").append(usr.pointer);
}
usr.pointer.css({left:x*$("#resizable").width()/me.brain_W,top:y*$("#resizable").height()/me.brain_H});
- break;
- }
- }
- usr.x0=x;
- usr.y0=y;
- },
+ break;
+ }
+ }
+ usr.x0=x;
+ usr.y0=y;
+ },
/**
* @function paintxy
* @desc Dispatches paint/erase commands to the annotation volume and to the server for broadcast
@@ -46,27 +46,27 @@ var AtlasMakerPaint = {
* @param {integer} y Y coordinate in slice space
* @param {Object} usr User object for the current user. Contains the painting value, view and slice
*/
- paintxy: function paintxy(u,c,x,y,usr) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(paintxy,1,"#0c0");if(l)console.log.apply(undefined,l);
-
- // u: user number
- // c: command
- // x, y: coordinates
- msg={c:c,x:x,y:y};
-
- if(u==-1 && JSON.stringify(msg)!=JSON.stringify(me.msg0)) {
- me.sendPaintMessage(msg);
- me.msg0=msg;
- }
-
- var dim=me.atlas.dim;
-
- var coord={x:x,y:y,z:usr.slice};
- if(usr.x0<0) {
- usr.x0=coord.x;
- usr.y0=coord.y;
- }
+ paintxy: function paintxy(u,c,x,y,usr) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(paintxy,1,"#0c0");if(l)console.log.apply(undefined,l);
+
+ // u: user number
+ // c: command
+ // x, y: coordinates
+ msg={c:c,x:x,y:y};
+
+ if(u==-1 && JSON.stringify(msg)!=JSON.stringify(me.msg0)) {
+ me.sendPaintMessage(msg);
+ me.msg0=msg;
+ }
+
+ var dim=me.atlas.dim;
+
+ var coord={x:x,y:y,z:usr.slice};
+ if(usr.x0<0) {
+ usr.x0=coord.x;
+ usr.y0=coord.y;
+ }
if(u!=-1) {
if(c === 'mu') {
@@ -98,30 +98,30 @@ var AtlasMakerPaint = {
break;
}
- usr.x0=coord.x;
- usr.y0=coord.y;
- },
+ usr.x0=coord.x;
+ usr.y0=coord.y;
+ },
/**
* @function paintvol
* @desc Paints a series of voxels as indicated in an array. This function is exclusively used for undoing
* @param {Array} voxels Array where each object contains a voxel index and a voxel value. The voxel index goes from 0 to dim[0]*dim[1]*dim[2]-1
*/
- paintvol: function paintvol(voxels) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(paintvol,0,"#0c0");if(l)console.log.apply(undefined,l);
-
- var i,
- ind, // voxel index
- val; // voxel delta-value, such that -=val undoes
- for(i=0;i0) {
- if(Q.length>max)
- max=Q.length;
- n=Q.shift();
- if(atlas.data[me.slice2index(n.x,n.y,z,myView)]!=bval)
- continue;
- left=n.x;
- right=n.x;
- y=n.y;
- while (left-1>=0 && atlas.data[me.slice2index(left-1,y,z,myView)]==bval) {
+ var Q=[],
+ left,
+ right,
+ n;
+ var i,max=0;
+ var bval=atlas.data[me.slice2index(x,y,z,myView)]; // background-value: value of the voxel where the click occurred
+
+ if(bval==val) // nothing to do
+ return;
+
+ Q.push({x:x,y:y});
+ while(Q.length>0) {
+ if(Q.length>max)
+ max=Q.length;
+ n=Q.shift();
+ if(atlas.data[me.slice2index(n.x,n.y,z,myView)]!=bval)
+ continue;
+ left=n.x;
+ right=n.x;
+ y=n.y;
+ while (left-1>=0 && atlas.data[me.slice2index(left-1,y,z,myView)]==bval) {
left--;
}
- while (right+1=0 && atlas.data[me.slice2index(x,y-1,z,myView)]==bval)
- Q.push({x:x,y:y-1});
- if(y+1=0 && atlas.data[me.slice2index(x,y-1,z,myView)]==bval)
+ Q.push({x:x,y:y-1});
+ if(y+1 -dy) {
- err -= dy;
- x1 += sx;
- }
- if (e2 < dx) {
- err += dx;
- y1 += sy;
- }
+ xyzi1=me.slice2xyzi(x1,y1,z,usr.view);
+ xyzi2=me.slice2xyzi(x2,y2,z,usr.view);
+ me.annotationLength+=Math.sqrt( Math.pow(me.brain_pixdim[0]*(xyzi1[0]-xyzi2[0]),2)+
+ Math.pow(me.brain_pixdim[1]*(xyzi1[1]-xyzi2[1]),2)+
+ Math.pow(me.brain_pixdim[2]*(xyzi1[2]-xyzi2[2]),2));
+
+ for(j=0;j -dy) {
+ err -= dy;
+ x1 += sx;
+ }
+ if (e2 < dx) {
+ err += dx;
+ y1 += sy;
+ }
for(j=0;j MRI");
- $("#chat").text("Chat (1 connected)");
- me.flagConnected = 1;
- me.reconnectionTimeout = 5;
- resolve();
- };
-
- me.receiveFunctions["saveMetadata"] = me.receiveMetadata;
- me.receiveFunctions["userData"] = me.receiveUserDataMessage;
- me.receiveFunctions["volInfo"] = function (data) { console.log("volInfo", data) };
- me.receiveFunctions["chat"] = me.receiveChatMessage;
- me.receiveFunctions["show"] = me.receiveShowMessage;
- me.receiveFunctions["paint"] = me.receivePaintMessage;
- me.receiveFunctions["paintvol"] = me.receivePaintVolumeMessage;
- me.receiveFunctions["disconnect"] = me.receiveDisconnectMessage;
- me.receiveFunctions["serverMessage"] = me.receiveServerMessage;
-
- me.receiveFunctions["requestSlice"] = function (data) { console.log("requestSlice", data) };
- me.receiveFunctions["requestSlice2"] = function (data) { console.log("requestSlice2", data) };
-
- me.socket.onmessage = me.receiveSocketMessage;
-
- me.socket.onclose = function (msg) {
- me.flagConnected = 0;
-
- // Try to reconnect
- // wait a random initial time, to prevent an avalanche
- // of reconnections in case of server crash
- var rand = 1000 + 5000 * Math.random();
- console.log("Initial random time:", rand);
- setTimeout(function () {
- var timeout = me.reconnectionTimeout;
- $("#chat").text("Disconnected. Try to reconnect in " + (timeout--) + " s...");
- if (me.timer) {
+ createSocket: function createSocket(host) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(createSocket,0,"#aca");if(l)console.log.apply(undefined,l);
+
+ var ws;
+
+ if (window.WebSocket) {
+ ws=new WebSocket(host);
+ } else if (window.MozWebSocket) {
+ ws=new MozWebSocket(host);
+ } else {
+ console.log("ERROR: browser does not support WebSockets");
+ }
+
+ return ws;
+ },
+ /**
+ * @function initSocketConnection
+ */
+ initSocketConnection: function initSocketConnection() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(initSocketConnection,0,"#aca");if(l)console.log.apply(undefined,l);
+
+ var def=$.Deferred();
+
+ // WS connection
+ var host = "ws://" + window.location.hostname + ":8080/";
+
+ if(me.debug)
+ console.log("[initSocketConnection] host:",host);
+ if (me.progress)
+ me.progress.html("Connecting...");
+
+ try {
+ me.socket = me.createSocket(host);
+
+ me.socket.onopen = function(msg) {
+ if(me.debug)
+ console.log("[initSocketConnection] connection open",msg);
+ me.progress.html(" MRI");
+ $("#chat").text("Chat (1 connected)");
+ me.flagConnected=1;
+ me.reconnectionTimeout = 5;
+ def.resolve();
+ };
+
+ me.receiveFunctions["saveMetadata"]=me.receiveMetadata;
+ me.receiveFunctions["userData"]=me.receiveUserDataMessage;
+ me.receiveFunctions["volInfo"]=function(data){console.log("volInfo",data)};
+ me.receiveFunctions["chat"]=me.receiveChatMessage;
+ me.receiveFunctions["show"]=me.receiveShowMessage;
+ me.receiveFunctions["paint"]=me.receivePaintMessage;
+ me.receiveFunctions["paintvol"]=me.receivePaintVolumeMessage;
+ me.receiveFunctions["disconnect"]=me.receiveDisconnectMessage;
+ me.receiveFunctions["serverMessage"]=me.receiveServerMessage;
+
+ me.receiveFunctions["requestSlice"]=function(data){console.log("requestSlice",data)};
+ me.receiveFunctions["requestSlice2"]=function(data){console.log("requestSlice2",data)};
+
+ me.socket.onmessage = me.receiveSocketMessage;
+
+ me.socket.onclose = function(msg) {
+ me.flagConnected=0;
+
+ // Try to reconnect
+ // wait a random initial time, to prevent an avalanche
+ // of reconnections in case of server crash
+ var rand = 1000+5000*Math.random();
+ console.log("Initial random time:",rand);
+ setTimeout(function() {
+ var timeout = me.reconnectionTimeout;
+ $("#chat").text("Disconnected. Try to reconnect in "+(timeout--)+" s...");
+ if(me.timer) {
+ clearInterval(me.timer);
+ }
+ me.timer = setInterval(function() {
+ if(timeout < 0) {
+ $("#chat").text("Reconnecting...");
+ me.socket = null;
clearInterval(me.timer);
+ setTimeout(function() {
+ me.reconnectionTimeout *= 2;
+ me.initSocketConnection()
+ .then(function() {
+ me.sendUserDataMessage("allUserData");
+ me.sendUserDataMessage("sendAtlas");
+ clearInterval(me.timer);
+ })
+ .catch(function() {
+ timeout=me.reconnectionTimeout;
+ $("#chat").text("Disconnected. Try to reconnect in "+(timeout--)+" s...");
+ });
+ }, 1000);
+ } else {
+ $("#chat").text("Disconnected. Try to reconnect in "+(timeout--)+" s...");
}
- me.timer = setInterval(function () {
- if (timeout < 0) {
- $("#chat").text("Reconnecting...");
- me.socket = null;
- clearInterval(me.timer);
- setTimeout(function () {
- me.reconnectionTimeout *= 2;
- me.initSocketConnection()
- .then(function () {
- me.sendUserDataMessage("allUserData");
- me.sendUserDataMessage("sendAtlas");
- clearInterval(me.timer);
- })
- .catch(function () {
- timeout = me.reconnectionTimeout;
- $("#chat").text("Disconnected. Try to reconnect in " + (timeout--) + " s...");
- });
- }, 1000);
- } else {
- $("#chat").text("Disconnected. Try to reconnect in " + (timeout--) + " s...");
- }
- }, 1000);
- }, rand);
- };
-
- window.onbeforeunload = function () {
- me.socket.onclose = function () { }; // disable onclose handler first
- me.socket.close()
- };
- }
- catch (ex) {
- $("#chat").text("Chat (not connected - connection error)");
- }
- })
- },
- /**
+ }, 1000);
+ }, rand);
+ };
+
+ window.onbeforeunload = function() {
+ me.socket.onclose = function () {}; // disable onclose handler first
+ me.socket.close()
+ };
+ }
+ catch (ex) {
+ $("#chat").text("Chat (not connected - connection error)");
+ }
+
+ return def.promise();
+ },
+ /**
* @function receiveSocketMessage
*/
- receiveSocketMessage: function receiveSocketMessage(msg) {
- var me = AtlasMakerWidget;
- var l = me.traceLog(receiveSocketMessage, 1, "#aca"); if (l) console.log.apply(undefined, l);
-
- // Message: atlas data initialisation
- if (msg.data instanceof Blob) {
- me.receiveBinaryMessage(msg.data);
- return;
- }
-
- // Message: interaction message
- var data = JSON.parse(msg.data);
- me.receiveFunctions[data.type](data);
- },
- /**
+ receiveSocketMessage: function receiveSocketMessage(msg) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(receiveSocketMessage,1,"#aca");if(l)console.log.apply(undefined,l);
+
+ // Message: atlas data initialisation
+ if(msg.data instanceof Blob) {
+ me.receiveBinaryMessage(msg.data);
+ return;
+ }
+
+ // Message: interaction message
+ var data=JSON.parse(msg.data);
+ me.receiveFunctions[data.type](data);
+ },
+ /**
* @function sendUserDataMessage
*/
- sendUserDataMessage: function sendUserDataMessage(description) {
- var me = AtlasMakerWidget;
- var l = me.traceLog(sendUserDataMessage, 1, "#aca"); if (l) console.log.apply(undefined, l);
-
- if (me.flagConnected == 0)
- return;
-
- if (me.debug > 1) console.log("message: " + description);
-
- if (description === "allUserData")
- var msg = { "type": "userData", "user": me.User, "description": description };
- else
- var msg = { "type": "userData", "description": description };
- try {
- me.socket.send(JSON.stringify(msg));
- } catch (ex) {
- console.log("ERROR: Unable to sendUserDataMessage", ex);
- }
- },
- /**
+ sendUserDataMessage: function sendUserDataMessage(description) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(sendUserDataMessage,1,"#aca");if(l)console.log.apply(undefined,l);
+
+ if(me.flagConnected==0)
+ return;
+
+ if(me.debug>1) console.log("message: "+description);
+
+ if(description === "allUserData")
+ var msg={"type":"userData","user":me.User,"description":description};
+ else
+ var msg={"type":"userData","description":description};
+ try {
+ me.socket.send(JSON.stringify(msg));
+ } catch (ex) {
+ console.log("ERROR: Unable to sendUserDataMessage",ex);
+ }
+ },
+ /**
* @function receiveBinaryMessage
*/
- receiveBinaryMessage: function receiveBinaryMessage(msgData) {
- var me = AtlasMakerWidget;
- var l = me.traceLog(receiveBinaryMessage, 1, "#aca"); if (l) console.log.apply(undefined, l);
-
+ receiveBinaryMessage: function receiveBinaryMessage(msgData) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(receiveBinaryMessage,1,"#aca");if(l)console.log.apply(undefined,l);
+
var fileReader = new FileReader();
fileReader.onload = function from_receiveSocketMessage() {
- var data = new Uint8Array(this.result);
- var sz = data.length;
- var ext = String.fromCharCode(data[sz - 8], data[sz - 7], data[sz - 6]);
-
- if (me.debug > 1) console.log("type: " + ext);
+ var data=new Uint8Array(this.result);
+ var sz=data.length;
+ var ext=String.fromCharCode(data[sz-8],data[sz-7],data[sz-6]);
- switch (ext) {
+ if(me.debug>1) console.log("type: "+ext);
+
+ switch(ext) {
case 'nii': {
- var inflate = new pako.Inflate();
- inflate.push(data, true);
- var atlas = new Object();
- atlas.data = inflate.result;
- atlas.name = me.atlasFilename;
- atlas.dim = me.brain_dim;
-
- me.atlas = atlas;
+ var inflate=new pako.Inflate();
+ inflate.push(data,true);
+ var atlas=new Object();
+ atlas.data=inflate.result;
+ atlas.name=me.atlasFilename;
+ atlas.dim=me.brain_dim;
+
+ me.atlas=atlas;
me.configureBrainImage();
me.configureAtlasImage();
me.resizeWindow();
- me.brain_img.img = null;
+ me.brain_img.img=null;
me.drawImages();
-
+
// compute total segmented volume
- var vol = me.computeSegmentedVolume();
- me.info.volume = parseInt(vol) + " mm3";
+ var vol=me.computeSegmentedVolume();
+ me.info.volume=parseInt(vol)+" mm3";
// setup download link
- var link = me.container.find("span#download_atlas");
- link.html(" " + atlas.name);
+ var link=me.container.find("span#download_atlas");
+ link.html(" "+atlas.name);
break;
}
@@ -205,283 +207,283 @@ var AtlasMakerWS = {
var urlCreator = window.URL || window.webkitURL;
var imageUrl = urlCreator.createObjectURL(msgData);
var img = new Image();
-
- me.isMRILoaded = true; // receiving a jpg is proof of a loaded MRI
-
- img.onload = function from_initSocketConnection() {
- var flagFirstImage = (me.brain_img.img == null);
- me.brain_img.img = img;
- me.brain_img.view = me.flagLoadingImg.view;
- me.brain_img.slice = me.flagLoadingImg.slice;
+
+ me.isMRILoaded=true; // receiving a jpg is proof of a loaded MRI
+
+ img.onload=function from_initSocketConnection(){
+ var flagFirstImage=(me.brain_img.img==null);
+ me.brain_img.img=img;
+ me.brain_img.view=me.flagLoadingImg.view;
+ me.brain_img.slice=me.flagLoadingImg.slice;
me.drawImages();
+
+ me.flagLoadingImg.loading=false;
- me.flagLoadingImg.loading = false;
-
- if (flagFirstImage || me.flagLoadingImg.view != me.User.view || me.flagLoadingImg.slice != me.User.slice) {
+ if(flagFirstImage || me.flagLoadingImg.view!=me.User.view ||me.flagLoadingImg.slice!=me.User.slice) {
me.sendRequestSliceMessage();
}
-
+
// remove loading indicator
$("#loadingIndicator").hide();
}
- img.src = imageUrl;
+ img.src=imageUrl;
break;
}
}
};
fileReader.readAsArrayBuffer(msgData);
- },
- /**
+ },
+ /**
* @function receiveUserDataMessage
*/
- receiveUserDataMessage: function receiveUserDataMessage(data) {
- var me = AtlasMakerWidget;
- var l = me.traceLog(receiveUserDataMessage, 0, "#aca"); if (l) console.log.apply(undefined, l);
-
- if (me.debug > 1) console.log("description: " + data.description, data);
-
- var u = data.uid;
-
- // First time the user is observed
- if (me.Collab[u] === undefined) {
- try {
- //var msg=""+data.user.username+" entered atlas "+data.user.specimenName+"/"+data.user.atlasFilename+" "
- var msg;
- if (data.user === undefined || data.user.username === "Anonymous") {
- msg = "" + data.uid + " entered ";
- } else {
- msg = "" + data.user.username + " entered ";
- }
- $("#log").append(msg);
- $("#log").scrollTop($("#log")[0].scrollHeight);
- } catch (e) {
- console.log("data:", data);
- console.log(e);
- }
- }
-
- if (data.description === "allUserData")
- me.Collab[u] = data.user;
- else {
- try {
+ receiveUserDataMessage: function receiveUserDataMessage(data) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(receiveUserDataMessage,0,"#aca");if(l)console.log.apply(undefined,l);
+
+ if(me.debug>1) console.log("description: "+data.description,data);
+
+ var u=data.uid;
+
+ // First time the user is observed
+ if(me.Collab[u]===undefined) {
+ try {
+ //var msg=""+data.user.username+" entered atlas "+data.user.specimenName+"/"+data.user.atlasFilename+" "
+ var msg;
+ if(data.user === undefined || data.user.username === "Anonymous") {
+ msg=""+data.uid+" entered ";
+ } else {
+ msg=""+data.user.username+" entered ";
+ }
+ $("#log").append(msg);
+ $("#log").scrollTop($("#log")[0].scrollHeight);
+ } catch (e) {
+ console.log("data:",data);
+ console.log(e);
+ }
+ }
+
+ if(data.description === "allUserData")
+ me.Collab[u]=data.user;
+ else {
+ try {
var changes = JSON.parse(data.description);
var i;
- for (i in changes)
+ for(i in changes)
me.Collab[u][i] = changes[i];
} catch (e) {
console.log(e);
}
- }
-
- var v, nusers = 1;
- for (v in me.Collab)
- nusers++;
- $("#chat").text("Chat (" + nusers + " connected)");
- },
- /**
+ }
+
+ var v,nusers=1;
+ for(v in me.Collab)
+ nusers++;
+ $("#chat").text("Chat ("+nusers+" connected)");
+ },
+ /**
* @function sendChatMessage
*/
- sendChatMessage: function sendChatMessage() {
- var me = AtlasMakerWidget;
- var l = me.traceLog(sendChatMessage, 0, "#aca"); if (l) console.log.apply(undefined, l);
-
- if (me.flagConnected == 0)
- return;
- var msg = DOMPurify.sanitize($('input#msg')[0].value);
- try {
- me.socket.send(JSON.stringify({ "type": "chat", "msg": msg, "username": me.User.username }));
- var msg = "me: " + msg + " ";
- $("#log").append(msg);
- $("#log").scrollTop($("#log")[0].scrollHeight);
- $('input#msg').val("");
- } catch (ex) {
- console.log("ERROR: Unable to sendChatMessage", ex);
- }
- },
- /**
+ sendChatMessage: function sendChatMessage() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(sendChatMessage,0,"#aca");if(l)console.log.apply(undefined,l);
+
+ if(me.flagConnected==0)
+ return;
+ var msg = DOMPurify.sanitize($('input#msg')[0].value);
+ try {
+ me.socket.send(JSON.stringify({"type":"chat","msg":msg,"username":me.User.username}));
+ var msg="me: "+msg+" ";
+ $("#log").append(msg);
+ $("#log").scrollTop($("#log")[0].scrollHeight);
+ $('input#msg').val("");
+ } catch (ex) {
+ console.log("ERROR: Unable to sendChatMessage",ex);
+ }
+ },
+ /**
* @function receiveChatMessage
*/
- receiveChatMessage: function receiveChatMessage(data) {
- var me = AtlasMakerWidget;
- var l = me.traceLog(receiveChatMessage, 0, "#aca"); if (l) console.log.apply(undefined, l);
- console.log(data);
-
- var theSource = me.Collab[data.uid].source;
- var theView = me.Collab[data.uid].view;
- var theSlice = me.Collab[data.uid].slice;
- var link = "/mri?url=" + theSource + "&view=" + theView + "&slice=" + theSlice;
- var theUsername = data.username;
- var msg = ""+theUsername+": "+data.msg+" "
- $("#log").append(msg);
- $("#log").scrollTop($("#log")[0].scrollHeight);
- },
- /**
+ receiveChatMessage: function receiveChatMessage(data) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(receiveChatMessage,0,"#aca");if(l)console.log.apply(undefined,l);
+ console.log(data);
+
+ var theSource=me.Collab[data.uid].source;
+ var theView=me.Collab[data.uid].view;
+ var theSlice=me.Collab[data.uid].slice;
+ var link = "/mri?url="+theSource+"&view="+theView+"&slice="+theSlice;
+ var theUsername=data.username;
+ var msg=""+theUsername+": "+data.msg+" "
+ $("#log").append(msg);
+ $("#log").scrollTop($("#log")[0].scrollHeight);
+ },
+ /**
* @function sendPaintMessage
* @desc On user painting, this function broadcasts the painting event to all other connected users
* @param {Object} msg Painting event object: {"c":c,"x":x,"y":y}, where "c" is the command (l,e,lf,ef) and x and y are the coordinates in slice space
*/
- sendPaintMessage: function sendPaintMessage(msg) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(sendPaintMessage,1,"#aca");if(l)console.log.apply(undefined,l);
-
- if(me.flagConnected==0)
- return;
- try {
- me.socket.send(JSON.stringify({type:"paint",data:msg}));
- } catch (ex) {
- console.log("ERROR: Unable to sendPaintMessage",ex);
- }
- },
- /**
+ sendPaintMessage: function sendPaintMessage(msg) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(sendPaintMessage,1,"#aca");if(l)console.log.apply(undefined,l);
+
+ if(me.flagConnected==0)
+ return;
+ try {
+ me.socket.send(JSON.stringify({type:"paint",data:msg}));
+ } catch (ex) {
+ console.log("ERROR: Unable to sendPaintMessage",ex);
+ }
+ },
+ /**
* @function receivePaintMessage
* @desc Receive paint events from other connected users
*/
- receivePaintMessage: function receivePaintMessage(data) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(receivePaintMessage,3,"#aca");if(l)console.log.apply(undefined,l);
-
- var msg=data.data;
- var u=data.uid; // user
- var c=msg.c; // command
- var x=parseInt(msg.x); // x coordinate
- var y=parseInt(msg.y); // y coordinate
-
- if(me.Collab[u])
- me.paintxy(u,c,x,y,me.Collab[u]);
- },
- /**
+ receivePaintMessage: function receivePaintMessage(data) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(receivePaintMessage,3,"#aca");if(l)console.log.apply(undefined,l);
+
+ var msg=data.data;
+ var u=data.uid; // user
+ var c=msg.c; // command
+ var x=parseInt(msg.x); // x coordinate
+ var y=parseInt(msg.y); // y coordinate
+
+ if(me.Collab[u])
+ me.paintxy(u,c,x,y,me.Collab[u]);
+ },
+ /**
* @function sendShowMessage
* @desc On user showing, this function broadcasts the showing event to all other connected users
* @param {Object} msg Showing event object: {"x":x,"y":y}, where x and y are the coordinates in slice space
*/
- sendShowMessage: function sendShowMessage(msg) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(sendShowMessage,1,"#aca");if(l)console.log.apply(undefined,l);
-
- if(me.flagConnected==0)
- return;
- try {
- me.socket.send(JSON.stringify({type:"show",data:msg}));
- } catch (ex) {
- console.log("ERROR: Unable to sendShowMessage",ex);
- }
- },
- /**
+ sendShowMessage: function sendShowMessage(msg) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(sendShowMessage,1,"#aca");if(l)console.log.apply(undefined,l);
+
+ if(me.flagConnected==0)
+ return;
+ try {
+ me.socket.send(JSON.stringify({type:"show",data:msg}));
+ } catch (ex) {
+ console.log("ERROR: Unable to sendShowMessage",ex);
+ }
+ },
+ /**
* @function receiveShowMessage
* @desc Receive show events from other connected users
*/
- receiveShowMessage: function receiveShowMessage(data) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(receiveShowMessage,3,"#aca");if(l)console.log.apply(undefined,l);
-
- var msg=data.data;
- var u=data.uid; // user
- var c=msg.c; // command
- var x=parseInt(msg.x); // x coordinate
- var y=parseInt(msg.y); // y coordinate
-
- if(me.Collab[u])
- me.showxy(u,c,x,y,me.Collab[u]);
- },
- /**
+ receiveShowMessage: function receiveShowMessage(data) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(receiveShowMessage,3,"#aca");if(l)console.log.apply(undefined,l);
+
+ var msg=data.data;
+ var u=data.uid; // user
+ var c=msg.c; // command
+ var x=parseInt(msg.x); // x coordinate
+ var y=parseInt(msg.y); // y coordinate
+
+ if(me.Collab[u])
+ me.showxy(u,c,x,y,me.Collab[u]);
+ },
+ /**
* @function receivePaintVolumeMessage
*/
- receivePaintVolumeMessage: function receivePaintVolumeMessage(data) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(receivePaintVolumeMessage,0,"#aca");if(l)console.log.apply(undefined,l);
-
- var i,ind,val,voxels;
-
- voxels=data.data;
- me.paintvol(voxels.data);
-
- /*
- TEST
- */
- me.sendRequestSliceMessage();
- },
- /**
+ receivePaintVolumeMessage: function receivePaintVolumeMessage(data) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(receivePaintVolumeMessage,0,"#aca");if(l)console.log.apply(undefined,l);
+
+ var i,ind,val,voxels;
+
+ voxels=data.data;
+ me.paintvol(voxels.data);
+
+ /*
+ TEST
+ */
+ me.sendRequestSliceMessage();
+ },
+ /**
* @function sendUndoMessage
*/
- sendUndoMessage: function sendUndoMessage() {
- var me=AtlasMakerWidget;
- var l=me.traceLog(sendUndoMessage,0,"#aca");if(l)console.log.apply(undefined,l);
-
- if(me.flagConnected==0)
- return;
- try {
- me.socket.send(JSON.stringify({type:"paint",data:{c:"u"}}));
- } catch (ex) {
- console.log("ERROR: Unable to sendUndoMessage",ex);
- }
- },
- /**
+ sendUndoMessage: function sendUndoMessage() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(sendUndoMessage,0,"#aca");if(l)console.log.apply(undefined,l);
+
+ if(me.flagConnected==0)
+ return;
+ try {
+ me.socket.send(JSON.stringify({type:"paint",data:{c:"u"}}));
+ } catch (ex) {
+ console.log("ERROR: Unable to sendUndoMessage",ex);
+ }
+ },
+ /**
* @function sendSaveMessage
*/
- sendSaveMessage: function sendSaveMessage() {
- var me=AtlasMakerWidget;
- var l=me.traceLog(sendSaveMessage,0,"#aca");if(l)console.log.apply(undefined,l);
-
- if(me.flagConnected==0)
- return;
- try {
- me.socket.send(JSON.stringify({type:"save"}));
- } catch (ex) {
- console.log("ERROR: Unable to sendSaveMessage",ex);
- }
- },
- /**
+ sendSaveMessage: function sendSaveMessage() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(sendSaveMessage,0,"#aca");if(l)console.log.apply(undefined,l);
+
+ if(me.flagConnected==0)
+ return;
+ try {
+ me.socket.send(JSON.stringify({type:"save"}));
+ } catch (ex) {
+ console.log("ERROR: Unable to sendSaveMessage",ex);
+ }
+ },
+ /**
* @function sendRequestMRIMessage
*/
- sendRequestMRIMessage: function sendRequestMRIMessage(source) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(sendRequestMRIMessage,1,"#aca");if(l)console.log.apply(undefined,l);
-
- if(me.flagConnected==0)
- return;
-
- try {
- me.socket.send(JSON.stringify({
- type:"requestMRI",
- source:"sendRequestMRIMessage"
- }));
- } catch (ex) {
- console.log("ERROR: Unable to sendRequestMRIMessage",ex);
- }
- },
- /**
+ sendRequestMRIMessage: function sendRequestMRIMessage(source) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(sendRequestMRIMessage,1,"#aca");if(l)console.log.apply(undefined,l);
+
+ if(me.flagConnected==0)
+ return;
+
+ try {
+ me.socket.send(JSON.stringify({
+ type:"requestMRI",
+ source:"sendRequestMRIMessage"
+ }));
+ } catch (ex) {
+ console.log("ERROR: Unable to sendRequestMRIMessage",ex);
+ }
+ },
+ /**
* @function sendRequestSliceMessage
*/
- sendRequestSliceMessage: function sendRequestSliceMessage() {
- var me=AtlasMakerWidget;
- var l=me.traceLog(sendRequestSliceMessage,1,"#aca");if(l)console.log.apply(undefined,l);
-
- if(me.flagConnected==0)
- return;
- if(me.flagLoadingImg.loading==true)
- return;
- try {
- me.socket.send(JSON.stringify({
-
- type:"requestSlice",
- /*
- TEST
- */
- //type:"requestSlice2",
-
- view:me.User.view,
- slice:me.User.slice
- }));
- me.flagLoadingImg.loading=true;
- me.flagLoadingImg.view=me.User.view;
- me.flagLoadingImg.slice=me.User.slice;
-
- } catch (ex) {
- console.log("ERROR: Unable to sendRequestSliceMessage",ex);
- }
- },
+ sendRequestSliceMessage: function sendRequestSliceMessage() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(sendRequestSliceMessage,1,"#aca");if(l)console.log.apply(undefined,l);
+
+ if(me.flagConnected==0)
+ return;
+ if(me.flagLoadingImg.loading==true)
+ return;
+ try {
+ me.socket.send(JSON.stringify({
+
+ type:"requestSlice",
+ /*
+ TEST
+ */
+ //type:"requestSlice2",
+
+ view:me.User.view,
+ slice:me.User.slice
+ }));
+ me.flagLoadingImg.loading=true;
+ me.flagLoadingImg.view=me.User.view;
+ me.flagLoadingImg.slice=me.User.slice;
+
+ } catch (ex) {
+ console.log("ERROR: Unable to sendRequestSliceMessage",ex);
+ }
+ },
/**
* @todo This is really not the place for some of this code. The receiveMetadata
* function is ok, but the direct references to projectInfo -- a structure
@@ -489,136 +491,136 @@ var AtlasMakerWS = {
* mechanism for uncoupling the 2 pieces of code is not clear. It could be
* a subscription, for example.
*/
- receiveMetadata: function receiveMetadata(data) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(receiveMetadata,1,"#aca");if(l)console.log.apply(undefined,l);
+ receiveMetadata: function receiveMetadata(data) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(receiveMetadata,1,"#aca");if(l)console.log.apply(undefined,l);
var projShortname = projectInfo.shortname;
- for (var i in projectInfo.files.list) {
- if (projectInfo.files.list[i].source == data.metadata.source) {
- for (var key in projectInfo.files.list[i].mri.annotations[projShortname]) {
- info_proxy["files.list." + i + ".mri.annotations." + projShortname + "." + key] = data.metadata.mri.annotations[projShortname][key];
- }
- info_proxy["files.list." + i + ".name"] = data.metadata.name;
- break;
- }
- }
- },
- /**
+ for (var i in projectInfo.files.list) {
+ if (projectInfo.files.list[i].source == data.metadata.source) {
+ for (var key in projectInfo.files.list[i].mri.annotations[projShortname]) {
+ info_proxy["files.list." + i + ".mri.annotations." + projShortname + "." + key] = data.metadata.mri.annotations[projShortname][key];
+ }
+ info_proxy["files.list." + i + ".name"] = data.metadata.name;
+ break;
+ }
+ }
+ },
+ /**
* @function sendSaveMetadataMessage
*/
- sendSaveMetadataMessage: function sendSaveMetadataMessage(info, method, patch) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(sendSaveMetadataMessage,1,"#aca");if(l)console.log.apply(undefined,l);
-
- return new Promise(function(resolve, reject) {
- if(me.flagConnected==0) {
- console.log("WARNING: Not connected: will not save metadata");
- return reject();
+ sendSaveMetadataMessage: function sendSaveMetadataMessage(info, method, patch) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(sendSaveMetadataMessage,1,"#aca");if(l)console.log.apply(undefined,l);
+
+ var def = $.Deferred();
+ if(me.flagConnected==0) {
+ console.log("WARNING: Not connected: will not save metadata");
+ return def.reject().promise();
+ }
+
+ try {
+ var rnd = Math.random().toString(36).slice(20);
+ var met = method || "append";
+ if(method == "patch") {
+ me.socket.send(JSON.stringify({
+ type:"saveMetadata",
+ metadata: info,
+ method: met,
+ patch: patch,
+ rnd: rnd
+ }));
+ } else {
+ me.socket.send(JSON.stringify({
+ type:"saveMetadata",
+ metadata: info,
+ method: met,
+ rnd: rnd
+ }));
}
-
- try {
- var rnd = Math.random().toString(36).slice(20);
- var met = method || "append";
- if(method == "patch") {
- me.socket.send(JSON.stringify({
- type:"saveMetadata",
- metadata: info,
- method: met,
- patch: patch,
- rnd: rnd
- }));
- } else {
- me.socket.send(JSON.stringify({
- type:"saveMetadata",
- metadata: info,
- method: met,
- rnd: rnd
- }));
- }
- if(me.debug>1) {
- console.log(rnd);
- console.log(info);
- }
- resolve();
-
- } catch (ex) {
- console.log("ERROR: Unable to sendSaveMetadataMessage",ex);
- reject();
+ if(me.debug>1) {
+ console.log(rnd);
+ console.log(info);
}
- });
- },
- /**
+ def.resolve();
+
+ } catch (ex) {
+ console.log("ERROR: Unable to sendSaveMetadataMessage",ex);
+ def.reject();
+ }
+ return def.promise();
+ },
+ /**
* @function receiveDisconnectMessage
*/
- receiveDisconnectMessage: function receiveDisconnectMessage(data) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(receiveDisconnectMessage,0,"#aca");if(l)console.log.apply(undefined,l);
-
- var u=data.uid; // user
- if(me.Collab[u]) {
- var msg;
- if(me.Collab[u].username === undefined || me.Collab[u].username === "Anonymous")
- msg = ""+me.Collab[u].uid+" left ";
- else
+ receiveDisconnectMessage: function receiveDisconnectMessage(data) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(receiveDisconnectMessage,0,"#aca");if(l)console.log.apply(undefined,l);
+
+ var u=data.uid; // user
+ if(me.Collab[u]) {
+ var msg;
+ if(me.Collab[u].username === undefined || me.Collab[u].username === "Anonymous")
+ msg = ""+me.Collab[u].uid+" left ";
+ else
msg = ""+me.Collab[u].username+" left ";
- }
- else
- var msg=""+u+" left ";
- delete me.Collab[u];
- var v,nusers=1; for(v in me.Collab) nusers++;
- $("#chat").text("Chat ("+nusers+" connected)");
- $("#log").append(msg);
- $("#log").scrollTop($("#log")[0].scrollHeight);
- },
- /**
+ }
+ else
+ var msg=""+u+" left ";
+ delete me.Collab[u];
+ var v,nusers=1; for(v in me.Collab) nusers++;
+ $("#chat").text("Chat ("+nusers+" connected)");
+ $("#log").append(msg);
+ $("#log").scrollTop($("#log")[0].scrollHeight);
+ },
+ /**
* @function receiveServerMessage
*/
- receiveServerMessage: function receiveServerMessage(data) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(receiveServerMessage,0,"#aca");if(l)console.log.apply(undefined,l);
-
- var msg=data.msg;
- var prevMsg=$("#chat").text();
- $("#chat").text(msg);
- setTimeout(function(){$("#chat").text(prevMsg)},5000);
- },
- /**
- * @function replayWSTraffic
- * @desc Replays websocket traffic recorded at the served. Used for debugging
- * @param Array recorded An array of websocket messages recorded in the server
- */
- replayWSTraffic: function replayWSTraffic(recorded) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(replayWSTraffic,0,"#aca");if(l)console.log.apply(undefined,l);
- var i;
- for(i=0;il)) {
var str,arg=[];
// str="am> "+(f.name)+" "+(f.caller?(f.caller.name||"annonymous"):"root");
@@ -103,141 +103,142 @@ var AtlasMakerWidget = {
return arg;
}
*/
- },
+ },
/**
* @function quit
*/
- quit: function quit() {
- var me=AtlasMakerWidget;
- var l=me.traceLog(quit,0,"#bbd");if(l)console.log.apply(undefined,l);
-
- me.log("","Goodbye!");
- me.socket.close();
- me.socket = null;
- },
-
- //====================================================================================
- // Configuration
- //====================================================================================
+ quit: function quit() {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(quit,0,"#bbd");if(l)console.log.apply(undefined,l);
+
+ me.log("","Goodbye!");
+ me.socket.close();
+ me.socket = null;
+ },
+
+ //====================================================================================
+ // Configuration
+ //====================================================================================
/**
* @function initAtlasMaker
*/
- initAtlasMaker: function initAtlasMaker(elem) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(initAtlasMaker,0,"#bbd");if(l)console.log.apply(undefined,l);
-
- // check if user is loged in
- $.get("/loggedIn",function(res) {
- console.log(res);
- if(res.loggedIn)
- me.User.username=res.username
- else
- me.User.username='Anonymous';
- });
-
- // Create offscreen canvas for mri and atlas
- me.brain_offcn=document.createElement('canvas');
- me.brain_offtx=me.brain_offcn.getContext('2d');
- me.atlas_offcn=document.createElement('canvas');
- me.atlas_offtx=me.atlas_offcn.getContext('2d');
-
- // Set widget div (create one if none)
- if(elem==undefined) {
- me.container=$("
');
- me.canvas = me.container.find('canvas')[0];
- me.context = me.canvas.getContext('2d');
-
- // Add div to display slice number
- me.container.find("#resizable").append("
");
-
- // Add div to display slice number
- me.container.find("#resizable").append(" ");
-
- // Add cursor (a small div)
- me.container.find("#resizable").append("
");
-
- $('body').attr('data-toolbarDisplay','right');
-
- // Add precise cursor
- var isTouchArr=[];//["iPad","iPod"];
- var curDevice=navigator.userAgent.split(/[(;]/)[1];
- if($.inArray(curDevice,isTouchArr)>=0) {
- me.flagUsePreciseCursor=true;
- me.initCursor();
- }
-
- // Configure mouse events for desktop computers
- me.canvas.onmousedown = me.mousedown;
- me.canvas.onmousemove = me.mousemove;
- me.canvas.onmouseup = me.mouseup;
-
- // Connect event to respond to window resizing
- $(window).resize(function() {
- me.resizeWindow();
- });
-
- // get pointer to progress div
- me.progress=$("a.download_MRI");
-
- // Init the toolbar: load template, wire actions
- return new Promise(function(resolve, reject) {
- $.get("/templates/tools.html",function from_initAtlasMaker(html) {
- me.container.append(html);
-
- // intercept keyboard events
- $(document).keydown(function(e){me.keyDown(e)});
-
- // configure annotation tools
- $("#tools-minimized").click(function(){me.changeToolbarDisplay("maximize")});
- me.push($(".push#display-minimize"),function(){me.changeToolbarDisplay("minimize")});
- me.push($(".push#display-left"),function(){me.changeToolbarDisplay("left")});
- me.push($(".push#display-right"),function(){me.changeToolbarDisplay("right")});
- me.slider($(".slider#slice"),function(x){me.changeSlice(Math.round(x))});
- me.chose($(".chose#plane"),me.changeView);
- me.chose($(".chose#paintTool"),me.changeTool);
- me.chose($(".chose#penSize"),me.changePenSize);
- me.toggle($(".toggle#precise"),me.togglePreciseCursor);
- me.toggle($(".toggle#fill"),me.toggleFill);
- me.toggle($(".toggle#fullscreen"),me.toggleFullscreen);
- me.toggle($(".toggle#bubble"),me.toggleChat);
- me.push($(".push#3drender"),me.render3D);
- me.push($(".push#link"),me.link);
- me.push($(".push#upload"),me.upload);
- me.push($(".push#download"),me.download);
- me.push($(".push#color"),me.color);
- me.push($(".push#undo"),me.sendUndoMessage);
- me.push($(".push#save"),me.sendSaveMessage);
- me.push($(".push#prev"),me.prevSlice);
- me.push($(".push#next"),me.nextSlice);
-
- // connect chat message input
- $("#msg").keypress(function keypress_fromInitAtlasMaker(e) {me.onkey(e)});
-
- $("#tools-minimized").hide();
- })
- .then(function from_initAtlasMaker() {
- // Init web socket connection
- return me.initSocketConnection();
- }).then(function() {
- resolve()
- });
- });
- },
+ initAtlasMaker: function initAtlasMaker(elem) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(initAtlasMaker,0,"#bbd");if(l)console.log.apply(undefined,l);
+
+ // check if user is loged in
+ $.get("/loggedIn",function(res) {
+ console.log(res);
+ if(res.loggedIn)
+ me.User.username=res.username
+ else
+ me.User.username='Anonymous';
+ });
+
+ // Create offscreen canvas for mri and atlas
+ me.brain_offcn=document.createElement('canvas');
+ me.brain_offtx=me.brain_offcn.getContext('2d');
+ me.atlas_offcn=document.createElement('canvas');
+ me.atlas_offtx=me.atlas_offcn.getContext('2d');
+
+ // Set widget div (create one if none)
+ if(elem==undefined) {
+ me.container=$("
');
+ me.canvas = me.container.find('canvas')[0];
+ me.context = me.canvas.getContext('2d');
+
+ // Add div to display slice number
+ me.container.find("#resizable").append("
");
+
+ // Add div to display slice number
+ me.container.find("#resizable").append(" ");
+
+ // Add cursor (a small div)
+ me.container.find("#resizable").append("
");
+
+ $('body').attr('data-toolbarDisplay','right');
+
+ // Add precise cursor
+ var isTouchArr=[];//["iPad","iPod"];
+ var curDevice=navigator.userAgent.split(/[(;]/)[1];
+ if($.inArray(curDevice,isTouchArr)>=0) {
+ me.flagUsePreciseCursor=true;
+ me.initCursor();
+ }
+
+ // Configure mouse events for desktop computers
+ me.canvas.onmousedown = me.mousedown;
+ me.canvas.onmousemove = me.mousemove;
+ me.canvas.onmouseup = me.mouseup;
+
+ // Connect event to respond to window resizing
+ $(window).resize(function() {
+ me.resizeWindow();
+ });
+
+ // get pointer to progress div
+ me.progress=$("a.download_MRI");
+
+ // Init the toolbar: load template, wire actions
+ var def=$.Deferred();
+ $.get("/templates/tools.html",function from_initAtlasMaker(html) {
+ me.container.append(html);
+
+ // intercept keyboard events
+ $(document).keydown(function(e){me.keyDown(e)});
+
+ // configure annotation tools
+ $("#tools-minimized").click(function(){me.changeToolbarDisplay("maximize")});
+ me.push($(".push#display-minimize"),function(){me.changeToolbarDisplay("minimize")});
+ me.push($(".push#display-left"),function(){me.changeToolbarDisplay("left")});
+ me.push($(".push#display-right"),function(){me.changeToolbarDisplay("right")});
+ me.slider($(".slider#slice"),function(x){me.changeSlice(Math.round(x))});
+ me.chose($(".chose#plane"),me.changeView);
+ me.chose($(".chose#paintTool"),me.changeTool);
+ me.chose($(".chose#penSize"),me.changePenSize);
+ me.toggle($(".toggle#precise"),me.togglePreciseCursor);
+ me.toggle($(".toggle#fill"),me.toggleFill);
+ me.toggle($(".toggle#fullscreen"),me.toggleFullscreen);
+ me.toggle($(".toggle#bubble"),me.toggleChat);
+ me.push($(".push#3drender"),me.render3D);
+ me.push($(".push#link"),me.link);
+ me.push($(".push#upload"),me.upload);
+ me.push($(".push#download"),me.download);
+ me.push($(".push#color"),me.color);
+ me.push($(".push#undo"),me.sendUndoMessage);
+ me.push($(".push#save"),me.sendSaveMessage);
+ me.push($(".push#prev"),me.prevSlice);
+ me.push($(".push#next"),me.nextSlice);
+
+ // connect chat message input
+ $("#msg").keypress(function keypress_fromInitAtlasMaker(e) {me.onkey(e)});
+
+ $("#tools-minimized").hide();
+ })
+ .then(function from_initAtlasMaker() {
+ // Init web socket connection
+ return me.initSocketConnection();
+ }).then(function() {
+ def.resolve()
+ });
+
+ return def.promise();
+ },
/**
* @function configureAtlasMaker
*/
- configureAtlasMaker: function configureAtlasMaker(info,index) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(configureAtlasMaker,0,"#bbd");if(l)console.log.apply(undefined,l);
+ configureAtlasMaker: function configureAtlasMaker(info,index) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(configureAtlasMaker,0,"#bbd");if(l)console.log.apply(undefined,l);
var def=$.Deferred();
@@ -273,146 +274,151 @@ var AtlasMakerWidget = {
});
return def.promise();
- },
+ },
/**
* @function configureOntology
*/
- configureOntology: function configureOntology(json) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(configureOntology,0,"#bbd");if(l)console.log.apply(undefined,l);
-
- me.ontology=json
- me.ontology.valueToIndex=[];
- me.ontology.labels.forEach(function(o,i){me.ontology.valueToIndex[o.value]=i});
- // to clear the region name being displayed on the info text-layer when having used eyedrop
- delete me.info.region;
- },
+ configureOntology: function configureOntology(json) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(configureOntology,0,"#bbd");if(l)console.log.apply(undefined,l);
+
+ me.ontology=json
+ me.ontology.valueToIndex=[];
+ me.ontology.labels.forEach(function(o,i){me.ontology.valueToIndex[o.value]=i});
+ // to clear the region name being displayed on the info text-layer when having used eyedrop
+ delete me.info.region;
+ },
/**
* @function requestMRIInfo
* @desc Request to download an MRI, with polling to prevent hangouts on lengthy
* downloads
*/
- requestMRIInfo: function requestMRIInfo(source, def) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(requestMRIInfo,0,"#bbd");if(l)console.log.apply(undefined,l);
+ requestMRIInfo: function requestMRIInfo(source, def) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(requestMRIInfo,0,"#bbd");if(l)console.log.apply(undefined,l);
+
+ if(!def) {
+ var def=$.Deferred();
+ }
$.post("/mri/json",{url:source}, function(info) {
if(info.success == true) {
- return Promise.resolve(info);
+ def.resolve(info);
} else if(info.success == 'downloading') {
if(me.User.source != source)
return;
+ setTimeout(function(){me.requestMRIInfo(source,def)},2000);
$("#loadingIndicator p").text("Loading... "+parseInt(info.cur/info.len*100,10)+"%");
- return new Promise(function(resolve, reject) {
- setTimeout(function(){
- resolve(me.requestMRIInfo(source))
- }, 2000);
- })
} else {
console.log("ERROR: requestMRIInfo",info);
- return Promise.reject();
+ def.reject();
}
});
- },
+
+ return def.promise();
+ },
/**
* @function configureMRI
*/
- configureMRI: function configureMRI(info,index) {
- var me=AtlasMakerWidget;
- var l=me.traceLog(configureMRI,0,"#bbd");if(l)console.log.apply(undefined,l);
-
- return new Promise(function(resolve, reject) {
- me.User.source=info.source;
- me.requestMRIInfo(info.source)
- .then( function(info2) {
-
- if(!info.dim) {
- // the mri object used to call this function does not have a 'dim'
- // property, indicating that it had not been downloaded at the time of the
- // call. Here we merge the fields from info2 that are initialised upon
- // download of the mri server-side. The mri field in the original 'info',
- // which contains the newly created text 'annotations', is conserved
- $.extend(true, info, info2);
- }
- info2=info;
-
- // Get data from AtlasMaker object
- me.name=info2.name||"Untitled";
- me.url=info2.url;
- me.atlasFilename=info2.mri.atlas[index].filename;
- me.atlasName=info2.mri.atlas[index].name;
-
- // get local file path from url
- me.User.dirname=me.url; // TEMPORARY
- me.User.mri=info2.mri.brain;
- me.User.specimenName=me.name;
- me.User.atlasFilename=info2.mri.atlas[index].filename;
- me.User.isMRILoaded=false;
-
- // TODO: it's silly to have to put vol dim twice...
- // (first here, once again further down)
- me.User.dim=info2.dim;
- me.User.pixdim=info2.pixdim;
-
- // compute space transformations
- me.User.v2w=info2.voxel2world;
- me.User.wori=info2.worldOrigin;
- me.computeS2VTransformation();
-
- //me.testS2VTransformation();
-
- me.flagLoadingImg={loading:false};
-
- me.brain_img.img=null;
-
- // get volume dimensions
- me.brain_dim=info2.dim;
- if(info2.pixdim)
- me.brain_pixdim=info2.pixdim;
- else
- me.brain_pixdim=[1,1,1];
-
- resolve(info2);
- })
- .catch(function(err) {
- console.log("ERROR: DOWNLOAD FAILED", err);
- reject(err);
- });
+ configureMRI: function configureMRI(info,index) {
+ var me=AtlasMakerWidget;
+ var l=me.traceLog(configureMRI,0,"#bbd");if(l)console.log.apply(undefined,l);
+
+ var def=$.Deferred();
+
+ me.User.source=info.source;
+ me.requestMRIInfo(info.source)
+ .then(function(info2) {
+
+ if(!info.dim) {
+ // the mri object used to call this function does not have a 'dim'
+ // property, indicating that it had not been downloaded at the time of the
+ // call. Here we merge the fields from info2 that are initialised upon
+ // download of the mri server-side. The mri field in the original 'info',
+ // which contains the newly created text 'annotations', is conserved
+ $.extend(true, info, info2);
+ }
+ info2=info;
+
+ // Get data from AtlasMaker object
+ me.name=info2.name||"Untitled";
+ me.url=info2.url;
+ me.atlasFilename=info2.mri.atlas[index].filename;
+ me.atlasName=info2.mri.atlas[index].name;
+
+ // get local file path from url
+ me.User.dirname=me.url; // TEMPORARY
+ me.User.mri=info2.mri.brain;
+ me.User.specimenName=me.name;
+ me.User.atlasFilename=info2.mri.atlas[index].filename;
+ me.User.isMRILoaded=false;
+
+ // TODO: it's silly to have to put vol dim twice...
+ // (first here, once again further down)
+ me.User.dim=info2.dim;
+ me.User.pixdim=info2.pixdim;
+
+ // compute space transformations
+ me.User.v2w=info2.voxel2world;
+ me.User.wori=info2.worldOrigin;
+ me.computeS2VTransformation();
+
+ //me.testS2VTransformation();
+
+ me.flagLoadingImg={loading:false};
+
+ me.brain_img.img=null;
+
+ // get volume dimensions
+ me.brain_dim=info2.dim;
+ if(info2.pixdim)
+ me.brain_pixdim=info2.pixdim;
+ else
+ me.brain_pixdim=[1,1,1];
+
+ def.resolve(info2);
+ })
+ .catch(function(err) {
+ console.log("ERROR: DOWNLOAD FAILED", err);
+ def.reject(err);
});
- }
+
+
+ return def.promise();
+ }
};
/*
- 0 int sizeof_hdr; //!< MUST be 348 // // int sizeof_hdr; //
- 4 char data_type[10]; //!< ++UNUSED++ // // char data_type[10]; //
- 14 char db_name[18]; //!< ++UNUSED++ // // char db_name[18]; //
- 32 int extents; //!< ++UNUSED++ // // int extents; //
- 36 short session_error; //!< ++UNUSED++ // // short session_error; //
- 38 char regular; //!< ++UNUSED++ // // char regular; //
- 39 char dim_info; //!< MRI slice ordering. // // char hkey_un0; //
-
- //--- was image_dimension substruct ---//
- 40 short dim[8]; //!< Data array dimensions.// // short dim[8]; //
- 56 float intent_p1 ; //!< 1st intent parameter. // // short unused8; //
- // short unused9; //
- 60 float intent_p2 ; //!< 2nd intent parameter. // // short unused10; //
- // short unused11; //
- 64 float intent_p3 ; //!< 3rd intent parameter. // // short unused12; //
- // short unused13; //
- 68 short intent_code ; //!< NIFTI_INTENT_* code. // // short unused14; //
- 70 short datatype; //!< Defines data type! // // short datatype; //
- 72 short bitpix; //!< Number bits/voxel. // // short bitpix; //
- 74 short slice_start; //!< First slice index. // // short dim_un0; //
- 76 float pixdim[8]; //!< Grid spacings. // // float pixdim[8]; //
- 108 float vox_offset; //!< Offset into .nii file // // float vox_offset; //
- 112 float scl_slope ; //!< Data scaling: slope. // // float funused1; //
- 116 float scl_inter ; //!< Data scaling: offset. // // float funused2; //
- 120 short slice_end; //!< Last slice index. // // float funused3; //
- 122 char slice_code ; //!< Slice timing order. //
- 123 char xyzt_units ; //!< Units of pixdim[1..4] //
- 124 float cal_max; //!< Max display intensity // // float cal_max; //
- 128 float cal_min; //!< Min display intensity // // float cal_min; //
- 132 float slice_duration;//!< Time for 1 slice. // // float compressed; //
- 136 float toffset; //!< Time axis shift. // // float verified; //
- 140 int glmax; //!< ++UNUSED++ // // int glmax; //
- 144 int glmin; //!< ++UNUSED++ // // int glmin; //
+ 0 int sizeof_hdr; //!< MUST be 348 // // int sizeof_hdr; //
+ 4 char data_type[10]; //!< ++UNUSED++ // // char data_type[10]; //
+ 14 char db_name[18]; //!< ++UNUSED++ // // char db_name[18]; //
+ 32 int extents; //!< ++UNUSED++ // // int extents; //
+ 36 short session_error; //!< ++UNUSED++ // // short session_error; //
+ 38 char regular; //!< ++UNUSED++ // // char regular; //
+ 39 char dim_info; //!< MRI slice ordering. // // char hkey_un0; //
+
+ //--- was image_dimension substruct ---//
+ 40 short dim[8]; //!< Data array dimensions.// // short dim[8]; //
+ 56 float intent_p1 ; //!< 1st intent parameter. // // short unused8; //
+ // short unused9; //
+ 60 float intent_p2 ; //!< 2nd intent parameter. // // short unused10; //
+ // short unused11; //
+ 64 float intent_p3 ; //!< 3rd intent parameter. // // short unused12; //
+ // short unused13; //
+ 68 short intent_code ; //!< NIFTI_INTENT_* code. // // short unused14; //
+ 70 short datatype; //!< Defines data type! // // short datatype; //
+ 72 short bitpix; //!< Number bits/voxel. // // short bitpix; //
+ 74 short slice_start; //!< First slice index. // // short dim_un0; //
+ 76 float pixdim[8]; //!< Grid spacings. // // float pixdim[8]; //
+ 108 float vox_offset; //!< Offset into .nii file // // float vox_offset; //
+ 112 float scl_slope ; //!< Data scaling: slope. // // float funused1; //
+ 116 float scl_inter ; //!< Data scaling: offset. // // float funused2; //
+ 120 short slice_end; //!< Last slice index. // // float funused3; //
+ 122 char slice_code ; //!< Slice timing order. //
+ 123 char xyzt_units ; //!< Units of pixdim[1..4] //
+ 124 float cal_max; //!< Max display intensity // // float cal_max; //
+ 128 float cal_min; //!< Min display intensity // // float cal_min; //
+ 132 float slice_duration;//!< Time for 1 slice. // // float compressed; //
+ 136 float toffset; //!< Time axis shift. // // float verified; //
+ 140 int glmax; //!< ++UNUSED++ // // int glmax; //
+ 144 int glmin; //!< ++UNUSED++ // // int glmin; //
*/
diff --git a/public/js/brainbox-intro.js b/public/js/brainbox-intro.js
index 68f41a8c..1bdcd674 100644
--- a/public/js/brainbox-intro.js
+++ b/public/js/brainbox-intro.js
@@ -1,31 +1,31 @@
-function startIntro() {
- const intro = introJs();
+function startIntro(){
+ var intro = introJs();
intro.setOptions({
steps: [
{
- intro: 'Welcome to BrainBox.' +
- 'BrainBox allows you to visualise and segment collaboratively ' +
- 'any brain MRI dataset available online. Follow this tutorial ' +
- 'to learn how to enter data into BrainBox, view it, edit it, ' +
- 'and create collaborative segmentation projects. BrainBox is an ' +
- 'open project – you will learn how to help us improving it by ' +
- 'reporting bugs and suggestions to our GitHub repository'
+ intro: "Welcome to BrainBox."
+ + "BrainBox allows you to visualise and segment collaboratively "
+ + "any brain MRI dataset available online. Follow this tutorial "
+ + "to learn how to enter data into BrainBox, view it, edit it, "
+ + "and create collaborative segmentation projects. BrainBox is an "
+ + "open project – you will learn how to help us improving it by "
+ + "reporting bugs and suggestions to our GitHub repository"
},
{
- element: '#url',
- intro: 'This is BrainBox\'s URL field. You can paste here a link ' +
- 'to any MRI on the web. Currently, BrainBox supports Nifti ' +
- 'format (.nii.gz files) and MGH format (.mgz files). Any link ' +
- 'on the Web should work, from Zenodo, FigShare, DropBox, Amazon, ' +
- 'etc. If you want to try BrainBox but you don\'t have any link to ' +
- 'an MRI, you can select a brain from the "Take me to a brain" ' +
- 'list, or browse among the community created projects.',
+ element: "#url",
+ intro: "This is BrainBox's URL field. You can paste here a link "
+ + "to any MRI on the web. Currently, BrainBox supports Nifti "
+ + "format (.nii.gz files) and MGH format (.mgz files). Any link "
+ + "on the Web should work, from Zenodo, FigShare, DropBox, Amazon, "
+ + "etc. If you want to try BrainBox but you don't have any link to "
+ + "an MRI, you can select a brain from the \"Take me to a brain\" "
+ + "list, or browse among the community created projects.",
position: 'top'
},
{
element: '#go',
- intro: 'Once you have entered the link to an MRI in the URL field ' +
- 'click the Go button to go to BrainBox\'s viewer'
+ intro: "Once you have entered the link to an MRI in the URL field "
+ + "click the Go button to go to BrainBox's viewer"
}
]
});
diff --git a/public/js/brainbox.js b/public/js/brainbox.js
index 62e1b3c0..9acb02ff 100644
--- a/public/js/brainbox.js
+++ b/public/js/brainbox.js
@@ -9,50 +9,50 @@
*/
var BrainBox={
- version: 1,
- debug: 1,
- info:{},
- labelSets:null,
- annotationType:["volume","text"],
- accessLevels: ["none","view","edit","add","remove"],
+ version: 1,
+ debug: 1,
+ info:{},
+ labelSets:null,
+ annotationType:["volume","text"],
+ accessLevels: ["none","view","edit","add","remove"],
/**
* @function traceLog
*/
- traceLog: function traceLog(f,l) {
- /*
- if(BrainBox.debug && (l==undefined || BrainBox.debug>l))
- // return "bb> "+(f.name)+" "+(f.caller?(f.caller.name||"annonymous"):"root");
- return "bb> ";//+(f.name);
- */
- },
+ traceLog: function traceLog(f,l) {
+ /*
+ if(BrainBox.debug && (l==undefined || BrainBox.debug>l))
+ // return "bb> "+(f.name)+" "+(f.caller?(f.caller.name||"annonymous"):"root");
+ return "bb> ";//+(f.name);
+ */
+ },
- /*
- JavaScript implementation of Java's hashCode method from
- http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
- */
- /**
+ /*
+ JavaScript implementation of Java's hashCode method from
+ http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
+ */
+ /**
* @function hash
*/
- hash: function hash(str) {
- var l=BrainBox.traceLog(hash);if(l)console.log(l);
-
- var v0=0,v1,abc="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
- for(i=0;i ');
- $("#atlasMaker").addClass('edit-mode');
-
- BrainBox.loadScript('/lib/jquery-ui.min.js', function(){return window.jQuery.ui != undefined})
- .then(function(){return BrainBox.loadScript('/lib/pako/pako.min.js', function(){return window.pako != undefined})})
- .then(function(){return BrainBox.loadScript('/lib/purify.min.js', function(){return window.DOMPurify != undefined})})
- .then(function(){return BrainBox.loadScript('/lib/json-patch-duplex.min.js', function(){return window.jsonpatch != undefined})})
- .then(function(){return BrainBox.loadScript('/lib/npm-bundle.js')})
- .then(function(){return BrainBox.loadScript('/js/twoWayBinding.js')})
- .then(function(){
- $.when(
- BrainBox.loadScript('/js/atlasMaker-draw.js'),
- BrainBox.loadScript('/js/atlasMaker-interaction.js'),
- BrainBox.loadScript('/js/atlasMaker-io.js'),
- BrainBox.loadScript('/js/atlasMaker-paint.js'),
- BrainBox.loadScript('/js/atlasMaker-ui.js'),
- BrainBox.loadScript('/js/atlasMaker-ws.js'),
- BrainBox.loadScript('/js/atlasMaker.js')
- ).then(function () {
- $.extend(AtlasMakerWidget,AtlasMakerDraw);
- $.extend(AtlasMakerWidget,AtlasMakerInteraction);
- $.extend(AtlasMakerWidget,AtlasMakerIO);
- $.extend(AtlasMakerWidget,AtlasMakerPaint);
- $.extend(AtlasMakerWidget,AtlasMakerUI);
- $.extend(AtlasMakerWidget,AtlasMakerWS);
- AtlasMakerWidget.initAtlasMaker($("#atlasMaker"))
- .then(function() {
- resolve();
- });
- })
- });
+ initBrainBox: function initBrainBox() {
+ var l=BrainBox.traceLog(initBrainBox);if(l)console.log(l);
+
+ var def=$.Deferred();
- // store state on exit
- $(window).on('unload',BrainBox.unload);
+ // Add AtlasMaker and friends
+ $("#stereotaxic").html('Downloading from source to server...");
-
- // Configure MRI into atlasMaker
- if(param.info.success===false) {
- date=new Date();
- $("#msgLog").append("
ERROR: "+param.info.message+".");
- return reject();
- }
- BrainBox.info=param.info;
+ configureBrainBox: function configureBrainBox(param) {
+ var l=BrainBox.traceLog(configureBrainBox);if(l)console.log(l);
+
+ var def=$.Deferred();
+ var date=new Date();
+ var index=param.annotationItemIndex||0;
+
+ // Copy MRI from source
+ $("#msgLog").html("
Downloading from source to server...");
- var arr=param.url.split("/");
- var name=arr[arr.length-1];
- date=new Date();
- $("#msgLog").append("
Downloading from server...");
-
- /**
- * @todo Check it these two lines are of any use...
- */
- param.dim=BrainBox.info.dim; // this allows to keep dim and pixdim through annotation changes
- param.pixdim=BrainBox.info.pixdim;
-
- // re-instance stored configuration
- var stored=localStorage.AtlasMaker;
- if(stored) {
- var stored=JSON.parse(stored);
- if(stored.version && stored.version==BrainBox.version) {
- for(var i=0;iERROR: "+param.info.message+".");
+ console.log("ERROR: "+param.info.message+".");
+ return def.promise().reject();
+ }
+ BrainBox.info=param.info;
- // enact configuration in param, eventually overriding the stored one
- if(param.view) {
- AtlasMakerWidget.User.view=param.view;
- AtlasMakerWidget.User.slice=null; // this will set the slider to the middle slice in case no slice were specified
- }
- if(param.slice)
- AtlasMakerWidget.User.slice=param.slice;
+ var arr=param.url.split("/");
+ var name=arr[arr.length-1];
+ date=new Date();
+ $("#msgLog").append("
Downloading from server...");
- if(param.fullscreen)
- AtlasMakerWidget.fullscreen=param.fullscreen;
- else
- AtlasMakerWidget.fullscreen=false;
+ /**
+ * @todo Check it these two lines are of any use...
+ */
+ param.dim=BrainBox.info.dim; // this allows to keep dim and pixdim through annotation changes
+ param.pixdim=BrainBox.info.pixdim;
- AtlasMakerWidget.configureAtlasMaker(BrainBox.info,index)
- .then(function(info2) {
- BrainBox.info = info2;
+ // re-instance stored configuration
+ var stored=localStorage.AtlasMaker;
+ if(stored) {
+ var stored=JSON.parse(stored);
+ if(stored.version && stored.version==BrainBox.version) {
+ for(var i=0;iBrainBox.accessLevels.length-1)
- accessLvl = 0;
- if(accessLvl>=2)
- AtlasMakerWidget.editMode = 1;
- else
- AtlasMakerWidget.editMode = 0;
+ // enact configuration in param, eventually overriding the stored one
+ if(param.view) {
+ AtlasMakerWidget.User.view=param.view;
+ AtlasMakerWidget.User.slice=null; // this will set the slider to the middle slice in case no slice were specified
+ }
+ if(param.slice)
+ AtlasMakerWidget.User.slice=param.slice;
- resolve();
- })
- .catch(function(err) {
- console.log("ERROR:",err);
- reject();
- });
+ if(param.fullscreen)
+ AtlasMakerWidget.fullscreen=param.fullscreen;
+ else
+ AtlasMakerWidget.fullscreen=false;
+
+ AtlasMakerWidget.configureAtlasMaker(BrainBox.info,index)
+ .then(function(info2) {
+ BrainBox.info = info2;
+
+ // check 'edit' access
+ var accessStr = BrainBox.info.mri.atlas[index].access;
+ var accessLvl = BrainBox.accessLevels.indexOf(accessStr);
+ if(accessLvl<0 || accessLvl>BrainBox.accessLevels.length-1)
+ accessLvl = 0;
+ if(accessLvl>=2)
+ AtlasMakerWidget.editMode = 1;
+ else
+ AtlasMakerWidget.editMode = 0;
+
+ def.resolve();
+ })
+ .catch(function(err) {
+ console.log("ERROR:",err);
+ def.reject();
});
- },
- /**
+
+ return def.promise();
+ },
+ /**
* @function convertImgObjectURLToDataURL
* @desc Encodes the ObjectURL obtained from the server jpg images as DataURL,
* suitable to be stored as a string in localStorage
*/
- convertImgObjectURLToDataURL: function convertImgObjectURLToDataURL(objURL) {
- return new Promise(function(resolve, reject) {
- var x = new XMLHttpRequest(), f = new FileReader();
- x.open('GET',objURL,true);
- x.responseType = 'blob';
- x.onload = function (e) {
- f.onload = function (evt) {
- resolve(evt.target.result);
- };
- f.readAsDataURL(x.response);
+ convertImgObjectURLToDataURL: function convertImgObjectURLToDataURL(objURL) {
+ var def = $.Deferred();
+ var x = new XMLHttpRequest(), f = new FileReader();
+ x.open('GET',objURL,true);
+ x.responseType = 'blob';
+ x.onload = function (e) {
+ f.onload = function (evt) {
+ def.resolve(evt.target.result);
};
- x.send();
- })
+ f.readAsDataURL(x.response);
+ };
+ x.send();
+ return def;
},
- /**
+ /**
* @function addCurrentMRIToHistory
*/
addCurrentMRIToHistory: function addCurrentMRIToHistory() {
var l=BrainBox.traceLog(addCurrentMRIToHistory);if(l)console.log(l);
- BrainBox.convertImgObjectURLToDataURL(AtlasMakerWidget.brain_img.img.src)
- .then(function(data) {
+ BrainBox.convertImgObjectURLToDataURL(AtlasMakerWidget.brain_img.img.src)
+ .then(function(data) {
var i, foundStored=false;
var stored=localStorage.AtlasMaker;
if(stored) {
@@ -245,7 +249,7 @@ var BrainBox={
}
if(foundStored==false)
stored={version:BrainBox.version,history:[]};
- stored.history.push({
+ stored.history.push({
url: BrainBox.info.source,
view: AtlasMakerWidget.User.view?AtlasMakerWidget.User.view.toLowerCase():"sag",
slice: AtlasMakerWidget.User.slice?AtlasMakerWidget.User.slice:0,
@@ -253,143 +257,143 @@ var BrainBox={
lastVisited: (new Date()).toJSON()
});
localStorage.AtlasMaker=JSON.stringify(stored);
- });
+ });
},
- /**
+ /**
* @function unload
*/
- unload: function unload() {
- /*
- var l=BrainBox.traceLog(unload);if(l)console.log(l);
- var i, obj0, obj1, foundStored=false;
- var stored=localStorage.AtlasMaker;
- if(stored) {
- stored=JSON.parse(stored);
- if(stored.version && stored.version==BrainBox.version) {
- foundStored=true;
- for(i=0;i=0 && currentIndex!=index) {
- console.log("bb>> change selected annotation");
- $(table).find("tr").removeClass("selected");
- $(table).find('tbody tr:eq('+index+')').addClass("selected");
- AtlasMakerWidget.configureAtlasMaker(BrainBox.info,index);
- }
- },
- /**
+ selectAnnotationTableRow: function selectAnnotationTableRow(index,param) {
+ var l=BrainBox.traceLog(selectAnnotationTableRow);if(l)console.log(l);
+
+ var table=param.table;
+ var currentIndex=$(table).find("tr.selected").index();
+
+ if(index>=0 && currentIndex!=index) {
+ console.log("bb>> change selected annotation");
+ $(table).find("tr").removeClass("selected");
+ $(table).find('tbody tr:eq('+index+')').addClass("selected");
+ AtlasMakerWidget.configureAtlasMaker(BrainBox.info,index);
+ }
+ },
+ /**
* @function appendAnnotationTableRow
*/
- appendAnnotationTableRow: function appendAnnotationTableRow(irow,param) {
- var l=BrainBox.traceLog(appendAnnotationTableRow);if(l)console.log(l);
-
- $(param.table).append(param.trTemplate);
+ appendAnnotationTableRow: function appendAnnotationTableRow(irow,param) {
+ var l=BrainBox.traceLog(appendAnnotationTableRow);if(l)console.log(l);
+
+ $(param.table).append(param.trTemplate);
- for(var icol=0;icol> 1)) : 0;
- }
- edge_table[i] = em;
- }
+ var k = 0;
+ for(var i=0; i<8; ++i) {
+ for(var j=1; j<=4; j<<=1) {
+ var p = i^j;
+ if(i <= p) {
+ cube_edges[k++] = i;
+ cube_edges[k++] = p;
+ }
+ }
+ }
+ for(var i=0; i<256; ++i) {
+ var em = 0;
+ for(var j=0; j<24; j+=2) {
+ var a = !!(i & (1<> 1)) : 0;
+ }
+ edge_table[i] = em;
+ }
}
function SurfaceNets(data, dims, pixdims, level) {
self.postMessage({msg:"SurfaceNets"});
- var vertices = [];
- var faces = [];
- var n = 0;
- var x = new Int32Array(3);
- var R = new Int32Array([1, (dims[0]+1), (dims[0]+1)*(dims[1]+1)]);
- var grid = new Float32Array(8);
- var buf_no = 1;
+ var vertices = [];
+ var faces = [];
+ var n = 0;
+ var x = new Int32Array(3);
+ var R = new Int32Array([1, (dims[0]+1), (dims[0]+1)*(dims[1]+1)]);
+ var grid = new Float32Array(8);
+ var buf_no = 1;
- if(R[2] * 2 > buffer.length)
- buffer = new Int32Array(R[2] * 2);
+ if(R[2] * 2 > buffer.length)
+ buffer = new Int32Array(R[2] * 2);
- for(x[2]=0; x[2] 1e-6)
- t = g0 / t;
- else
- continue;
- for(var j=0, k=1; j<3; ++j, k<<=1)
- {
- var a = e0 & k;
- var b = e1 & k;
- if(a !== b)
- v[j] += a ? 1.0 - t : t;
- else
- v[j] += a ? 1.0 : 0;
- }
- }
- var s = 1.0 / e_count;
- for(var i=0; i<3; ++i)
- v[i] = (x[i] + s * v[i])*pixdims[i];
- buffer[m] = vertices.length;
- vertices.push(v);
- for(var i=0; i<3; ++i)
- {
- if(!(edge_mask & (1< 1e-6)
+ t = g0 / t;
+ else
+ continue;
+ for(var j=0, k=1; j<3; ++j, k<<=1)
+ {
+ var a = e0 & k;
+ var b = e1 & k;
+ if(a !== b)
+ v[j] += a ? 1.0 - t : t;
+ else
+ v[j] += a ? 1.0 : 0;
+ }
+ }
+ var s = 1.0 / e_count;
+ for(var i=0; i<3; ++i)
+ v[i] = (x[i] + s * v[i])*pixdims[i];
+ buffer[m] = vertices.length;
+ vertices.push(v);
+ for(var i=0; i<3; ++i)
+ {
+ if(!(edge_mask & (1<
{{title}}
-
@@ -19,11 +18,11 @@