From c91398ee74748b0c84836e724b18559fcf29a3d4 Mon Sep 17 00:00:00 2001 From: Tarek Sherif Date: Mon, 14 Jul 2014 16:03:13 -0400 Subject: [PATCH] v2.0.1 --- .../brainbrowser.surface-viewer.min.js | 29 ++++++++++++++++++ .../brainbrowser.volume-viewer.min.js | 29 ++++++++++++++++++ .../workers/deindex.worker.js | 29 ++++++++++++++++++ .../workers/freesurferasc.intensity.worker.js | 29 ++++++++++++++++++ .../workers/freesurferasc.worker.js | 29 ++++++++++++++++++ .../brainbrowser-2.0.1/workers/json.worker.js | 29 ++++++++++++++++++ .../workers/mniobj.intensity.worker.js | 29 ++++++++++++++++++ .../workers/mniobj.worker.js | 29 ++++++++++++++++++ .../workers/wavefrontobj.worker.js | 29 ++++++++++++++++++ package.json | 2 +- release/brainbrowser-2.0.1.tar.gz | Bin 0 -> 22296 bytes 11 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 build/brainbrowser-2.0.1/brainbrowser.surface-viewer.min.js create mode 100644 build/brainbrowser-2.0.1/brainbrowser.volume-viewer.min.js create mode 100644 build/brainbrowser-2.0.1/workers/deindex.worker.js create mode 100644 build/brainbrowser-2.0.1/workers/freesurferasc.intensity.worker.js create mode 100644 build/brainbrowser-2.0.1/workers/freesurferasc.worker.js create mode 100644 build/brainbrowser-2.0.1/workers/json.worker.js create mode 100644 build/brainbrowser-2.0.1/workers/mniobj.intensity.worker.js create mode 100644 build/brainbrowser-2.0.1/workers/mniobj.worker.js create mode 100644 build/brainbrowser-2.0.1/workers/wavefrontobj.worker.js create mode 100644 release/brainbrowser-2.0.1.tar.gz diff --git a/build/brainbrowser-2.0.1/brainbrowser.surface-viewer.min.js b/build/brainbrowser-2.0.1/brainbrowser.surface-viewer.min.js new file mode 100644 index 00000000..04b16ef0 --- /dev/null +++ b/build/brainbrowser-2.0.1/brainbrowser.surface-viewer.min.js @@ -0,0 +1,29 @@ +/* +* BrainBrowser: Web-based Neurological Visualization Tools +* (https://brainbrowser.cbrain.mcgill.ca) +* +* Copyright (C) 2011 +* The Royal Institution for the Advancement of Learning +* McGill University +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +*/ + +/* +* BrainBrowser v2.0.1 +* +* Author: Tarek Sherif (http://tareksherif.ca/) +* Author: Nicolas Kassis +*/ +!function(){"use strict";var a="2.0.1";a=a.indexOf("BRAINBROWSER_VERSION")>0?"D.E.V":a,window.BrainBrowser={version:a},window.requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){return window.setTimeout(a,1e3/60)},window.cancelAnimationFrame=window.cancelAnimationFrame||function(a){window.clearTimeout(a)}}(),function(){"use strict";function a(b,c,d,e){return c>d?e(b):void Object.keys(b).forEach(function(f){a(b[f],c+1,d,e)})}BrainBrowser.createTreeStore=function(){var b={};return{set:function(){var a,c,d,e,f=arguments[arguments.length-1],g=Array.prototype.slice.call(arguments,0,arguments.length-1),h=b;for(c=0,d=g.length-1;d>c;c++){if(a=g[c],h[a]&&"object"!=typeof h[a])throw e="Hash key '["+g.slice(0,c+1).join("][")+"]' has already been set to a non-object value.\nCannot set '["+g.join("][")+"]'",BrainBrowser.events.triggerEvent("error",e),new Error(e);h[a]||(h[a]={}),h=h[a]}a=g[c],h[a]=f},get:function(){var a,c,d,e=Array.prototype.slice.call(arguments),f=b;if(0===e.length)return b;for(c=0,d=e.length-1;d>c;c++){if(a=e[c],void 0===f[a])return null;f=f[a]}return a=e[c],void 0!==f[a]?f[a]:null},remove:function(){var a,c,d,e,f=Array.prototype.slice.call(arguments),g=b;for(c=0,d=f.length-1;d>c;c++){if(a=f[c],void 0===g[a])return null;g=g[a]}return a=f[c],e=g[a],g[a]=void 0,e},reset:function(a){a=a&&"object"==typeof a?a:{},b=a},forEach:function(c,d){c=c>0?c:1,a(b,1,c,d)}}}}(),function(){"use strict";BrainBrowser.createColorMap=function(a){function b(a,b,d,e){var f,g,h,i=document.createElement("canvas"),j=new Array(256);for(i.width=256,i.height=d,f=0;256>f;f++)e?j[255-f]=f:j[f]=f;for(a=c.mapColors(j,{scale255:!0}),h=i.getContext("2d"),g=0;256>g;g++)h.fillStyle="rgb("+Math.floor(a[4*g])+", "+Math.floor(a[4*g+1])+", "+Math.floor(a[4*g+2])+")",h.fillRect(g,0,1,b);return i}var c={createCanvasWithScale:function(a,d,e){e=e||{};var f,g,h=c.colors,i=e.flip,j=d-a;return f=b(h,20,40,i),g=f.getContext("2d"),g.fillStyle="#FFA000",g.fillRect(.5,20,1,10),g.fillText(a.toPrecision(3),.5,40),g.fillRect(f.width/4,20,1,10),g.fillText((a+.25*j).toPrecision(3),.25*f.width,40),g.fillRect(f.width/2,20,1,10),g.fillText((a+.5*j).toPrecision(3),.5*f.width,40),g.fillRect(3*f.width/4,20,1,10),g.fillText((a+.75*j).toPrecision(3),.75*f.width,40),g.fillRect(f.width-.5,20,1,10),g.fillText(d.toPrecision(3),f.width-20,40),f},mapColors:function(a,b){b=b||{};var d,e,f,g,h=void 0===b.min?0:b.min,i=void 0===b.max?255:b.max,j=void 0===b.scale255?!1:b.scale255,k=void 0===b.brightness?0:b.brightness,l=void 0===b.contrast?1:b.contrast,m=void 0===b.alpha?1:b.alpha,n=b.destination||[],o=c.colors,p=o.length,q=i-h,r=(q+q/p)/p,s=j?255:1,t=[];for(m*=s,d=0,e=a.length;e>d;d++)g=a[d],f=h>=g?0:a[d]>i?p-1:Math.floor((g-h)/r),t=o[f]||[0,0,0],n[4*d+0]=s*(t[0]*l+k),n[4*d+1]=s*(t[1]*l+k),n[4*d+2]=s*(t[2]*l+k),n[4*d+3]=m;return n}};return function(){if(a){a=a.replace(/^\s+/,"").replace(/\s+$/,"");var b,d,e,f,g,h=a.split(/\n/),i=[];for(b=0,e=h.length;e>b;b++)if(g=h[b].replace(/^\s+/,"").replace(/\s+$/,"").split(/\s+/).slice(0,4),f=g.length,!(3>f)){for(d=0;f>d;d++)g[d]=parseFloat(g[d]);4>f&&g.push(1),i.push(g)}c.colors=i}}(),c}}(),function(){"use strict";var a=BrainBrowser.createTreeStore();BrainBrowser.config={set:function(b,c){b=b||"";var d=b.split(".");d.push(c),a.set.apply(a,d)},get:function(b){b=b||"";var c=b.split(".");return a.get.apply(a,c)}}}(),function(){"use strict";var a=[];BrainBrowser.events={addEventListener:function(b,c){a[b]||(a[b]=[]),a[b].push(c)},triggerEvent:function(b){var c=Array.prototype.slice.call(arguments,1);a[b]&&a[b].forEach(function(a){setTimeout(function(){a.apply(null,c)},0)})}}}(),function(){"use strict";var a=BrainBrowser.loader={loadFromURL:function(b,c,d){d=d||{};var e,f=new XMLHttpRequest,g=d.result_type,h=b.split("/"),i=h[h.length-1];f.open("GET",b),"arraybuffer"===g&&(f.responseType="arraybuffer"),f.onreadystatechange=function(){if(4===f.readyState){if(e=f.status,!(e>=200&&300>e||304===e)){var g="error loading URL: "+b+"\nHTTP Response: "+f.status+"\nHTTP Status: "+f.statusText+"\nResponse was: \n"+f.response;throw BrainBrowser.events.triggerEvent("error",g),new Error(g)}a.checkCancel(d)||c(f.response,i,d)}},f.send()},loadFromFile:function(a,b,c){var d=a.files;if(0!==d.length){c=c||{};var e=c.result_type,f=new FileReader,g=a.value.split("\\"),h=g[g.length-1];f.file=d[0],f.onloadend=function(a){b(a.target.result,h,c)},f.onerror=function(){var a="error reading file: "+h;throw BrainBrowser.events.triggerEvent("error",a),new Error(a)},"arraybuffer"===e?f.readAsArrayBuffer(d[0]):f.readAsText(d[0])}},loadColorMapFromURL:function(a,b,c){BrainBrowser.loader.loadFromURL(a,function(a,c,d){b(BrainBrowser.createColorMap(a),c,d)},c)},loadColorMapFromFile:function(a,b,c){BrainBrowser.loader.loadFromFile(a,function(a,c,d){b(BrainBrowser.createColorMap(a),c,d)},c)},checkCancel:function(a){a=a||{},BrainBrowser.utils.isFunction(a)&&(a={test:a});var b=a.test,c=a.cleanup,d=!1;return b&&b()&&(d=!0,c&&c()),d}}}(),function(){"use strict";BrainBrowser.utils={canvasEnabled:function(){return!!document.createElement("canvas")},webglEnabled:function(){var a=document.createElement("canvas");try{return!(!a||!window.WebGLRenderingContext||!a.getContext("webgl")&&!a.getContext("experimental-webgl"))}catch(b){return!1}},webWorkersEnabled:function(){return!!window.Worker},webGLErrorMessage:function(){var a,b='BrainBrowser requires WebGL.
';return b+=window.WebGLRenderingContext?"Your browser seems to support it, but it is
disabled or unavailable.
":"Your browser does not seem to support it.
",b+='Test your browser\'s WebGL support here.',a=document.createElement("div"),a.id="webgl-error",a.innerHTML=b,a},isFunction:function(a){return a instanceof Function||"function"==typeof a},isNumeric:function(a){return!isNaN(parseFloat(a))},min:function(){var a=Array.prototype.slice.call(arguments);a=1===a.length&&Array.isArray(a[0])?a[0]:a;var b,c,d=a[0];for(b=1,c=a.length;c>b;b++)a[b]b;b++)a[b]>d&&(d=a[b]);return d},getOffset:function(a){for(var b=0,c=0;a.offsetParent;)b+=a.offsetTop,c+=a.offsetLeft,a=a.offsetParent;return{top:b,left:c}},captureMouse:function(a){var b={x:0,y:0,left:!1,middle:!1,right:!1};return document.addEventListener("mousemove",function(c){var d,e,f=BrainBrowser.utils.getOffset(a);void 0!==c.pageX?(d=c.pageX,e=c.pageY):(d=c.clientX+window.pageXOffset,e=c.clientY+window.pageYOffset),b.x=d-f.left,b.y=e-f.top},!1),a.addEventListener("mousedown",function(a){a.preventDefault(),0===a.button&&(b.left=!0),1===a.button&&(b.middle=!0),2===a.button&&(b.right=!0)},!1),a.addEventListener("mouseup",function(a){a.preventDefault(),0===a.button&&(b.left=!1),1===a.button&&(b.middle=!1),2===a.button&&(b.right=!1)},!1),a.addEventListener("mouseleave",function(a){a.preventDefault(),b.left=b.middle=b.right=!1},!1),a.addEventListener("contextmenu",function(a){a.preventDefault()},!1),b},captureTouch:function(a){function b(b){var d,e,f,g,h,i=BrainBrowser.utils.getOffset(a);for(c.length=g=b.touches.length,f=0;g>f;f++)h=b.touches[f],void 0!==h.pageX?(d=h.pageX,e=h.pageY):(d=h.clientX+window.pageXOffset,e=h.clientY+window.pageYOffset),c[f]=c[f]||{},c[f].x=d-i.left,c[f].y=e-i.top}var c=[];return a.addEventListener("touchstart",b,!1),a.addEventListener("touchmove",b,!1),a.addEventListener("touchend",b,!1),c}}}(),function(){"use strict";function a(a){var c,d=BrainBrowser.config.get("worker_dir");if(null===d)throw c="error in SurfaceViewer configuration.\nBrainBrowser configuration parameter 'worker_dir' not defined.\nUse 'BrainBrowser.config.set(\"worker_dir\", ...)' to set it.",BrainBrowser.events.triggerEvent("error",c),new Error(c);var e,f={deindex:"deindex.worker.js"},g=0,h=BrainBrowser.config.get("model_types"),i=BrainBrowser.config.get("intensity_data_types");return null!==h&&Object.keys(h).forEach(function(a){f[a+"_model"]=h[a].worker}),null!==i&&Object.keys(i).forEach(function(a){f[a+"_intensity"]=i[a].worker}),e=Object.keys(f),0===e.length?void a():void(window.URL&&window.URL.createObjectURL?e.forEach(function(c){var h,i,j=d+"/"+f[c],k=new XMLHttpRequest;k.open("GET",j),k.onreadystatechange=function(){4===k.readyState&&(h=k.status,h>=200&&300>h||304===h?(i=new Blob([k.response],{type:"application/javascript"}),b.worker_urls[c]=window.URL.createObjectURL(i)):b.worker_urls[c]=j,++g===e.length&&a())},k.send()}):(e.forEach(function(a){b.worker_urls[a]=d+"/"+f[a]}),a()))}var b=BrainBrowser.SurfaceViewer={start:function(c,d){if(console.log("BrainBrowser Surface Viewer v"+BrainBrowser.version),!BrainBrowser.utils.webWorkersEnabled())return void alert("Can't find web workers. Exiting.");if(!BrainBrowser.utils.webglEnabled())return void alert("Can't get WebGL context. Exiting.");var e={},f=document.getElementById(c),g={dom_element:f,model:null,model_data:null,mouse:BrainBrowser.utils.captureMouse(f),touches:BrainBrowser.utils.captureTouch(f),getAttribute:function(a){return e[a]},setAttribute:function(a,b){e[a]=b},getVertex:function(a,b){b=b||{};var c=g.model_data.get(b.model_name).vertices,d=3*a;return new THREE.Vector3(c[d],c[d+1],c[d+2])}};return Object.keys(b.modules).forEach(function(a){b.modules[a](g)}),a(function(){d(g)}),g}};b.modules={},b.worker_urls={},BrainBrowser.config.set("model_types.json.worker","json.worker.js"),BrainBrowser.config.set("model_types.mniobj.worker","mniobj.worker.js"),BrainBrowser.config.set("model_types.wavefrontobj.worker","wavefrontobj.worker.js"),BrainBrowser.config.set("model_types.freesurferasc.worker","freesurferasc.worker.js"),BrainBrowser.config.set("intensity_data_types.mniobj.worker","mniobj.intensity.worker.js"),BrainBrowser.config.set("intensity_data_types.freesurferasc.worker","freesurferasc.intensity.worker.js")}(),BrainBrowser.SurfaceViewer.parseIntensityData=function(a,b,c){"use strict";function d(){var b=new Worker(BrainBrowser.SurfaceViewer.worker_urls[f]);b.addEventListener("message",function(a){var d,e=a.data;for(d in e)e.hasOwnProperty(d)&&(g[d]=e[d]);c&&c(g),b.terminate()}),b.postMessage({cmd:"parse",data:a})}var e,f=b+"_intensity";if(!BrainBrowser.SurfaceViewer.worker_urls[f])throw e="error in SurfaceViewer configuration.\nIntensity data worker URL for "+b+" not defined.\nUse 'BrainBrowser.config.set(\"intensity_data_types."+b+".worker\", ...)' to set it.",BrainBrowser.events.triggerEvent("error",e),new Error(e);var g={};a&&("string"==typeof a?d(a):a.values?(g.values=a.values.concat(),g.min=BrainBrowser.utils.min(g.values),g.max=BrainBrowser.utils.max(g.values)):(g.values=a,g.min=BrainBrowser.utils.min(a),g.max=BrainBrowser.utils.max(a)))},BrainBrowser.SurfaceViewer.modules.annotations=function(a){"use strict";function b(b){b=b||{};var c=b.model_name||null;return!c&&a.model.children[0]&&(c=a.model.children[0].model_name),c}var c=BrainBrowser.createTreeStore(),d=.5,e=65280,f=16711680;a.annotations={add:function(e,g,h){h=h||{};var i,j,k=b(h);k&&(j=a.getVertex(e,{model_name:h.model_name}),i=a.drawDot(j.x,j.y,j.z,d,f),i.annotation_info={data:g,model_name:k,vertex:e,position:j},c.set(k,e,i),h.activate!==!1&&this.activate(e,h))},get:function(a,d){d=d||{};var e,f=b(d);return f?(e=c.get(f,a),d.activate!==!1&&this.activate(a,d),e):null},remove:function(d,e){e=e||{};var f,g=b(e);return g?(f=c.remove(g,d),a.model.remove(f),f):null},reset:function(){this.forEach(function(b){a.model.remove(b)}),c.reset()},activate:function(a,b){b=b||{};var c=this.get(a,{model_name:b.model_name,activate:!1});c&&this.forEach(function(a){a.material.color.setHex(a===c?e:f)})},forEach:function(a){c.forEach(2,a)},setMarkerOnColor:function(a){e=a},setMarkerOffColor:function(a){f=a},setMarkerRadius:function(a){d=a}}},BrainBrowser.SurfaceViewer.modules.color=function(a){"use strict";function b(b,c,d){var e,f,g,h,i,j=b.values,k=a.model_data.get(c).colors,l=b.range_min,m=b.range_max,n=a.getAttribute("flip_colors"),o=a.getAttribute("clamp_colors"),p=a.color_map.colors,q=new Float32Array(4*j.length),r=p.length,s=m-l,t=(s+s/r)/r,u=!1;for(e=0,g=j.length;g>e;e++)i=j[e],u=!1,l>i?o?h=0:u=!0:i>m?o?h=r-1:u=!0:h=Math.floor((i-l)/t),f=4*e,u?4===k.length?(q[f]=k[0],q[f+1]=k[1],q[f+2]=k[2],q[f+3]=k[3]):(q[f]=k[4*e],q[f+1]=k[4*e+1],q[f+2]=k[4*e+2],q[f+3]=k[4*e+3]):n?(q[f]=p[r-1-h][0],q[f+1]=p[r-1-h][1],q[f+2]=p[r-1-h][2],q[f+3]=p[r-1-h][3]):(q[f]=p[h][0],q[f+1]=p[h][1],q[f+2]=p[h][2],q[f+3]=p[h][3]);d&&d(q)}function c(a,b){var c,d,e,f,g,h,i,j,k,l,m,n,o,p;for(i=0,k=b.length;k>i;i++){for(d=b[i],l=d.getObjectByName("__WIREFRAME__"),p=!!l,p&&(m=l.geometry.attributes.color.array),c=d.geometry,e=d.geometry.original_data.indices,f=c.attributes.color,g=f.array,h=0,j=e.length;j>h;h+=3)n=4*h,o=2*n,g[n]=a[4*e[h]],g[n+1]=a[4*e[h]+1],g[n+2]=a[4*e[h]+2],g[n+3]=1,g[n+4]=a[4*e[h+1]],g[n+5]=a[4*e[h+1]+1],g[n+6]=a[4*e[h+1]+2],g[n+7]=1,g[n+8]=a[4*e[h+2]],g[n+9]=a[4*e[h+2]+1],g[n+10]=a[4*e[h+2]+2],g[n+11]=1,p&&(m[o]=g[n],m[o+1]=g[n+1],m[o+2]=g[n+2],m[o+3]=g[n+3],m[o+4]=g[n+4],m[o+5]=g[n+5],m[o+6]=g[n+6],m[o+7]=g[n+7],m[o+8]=g[n+4],m[o+9]=g[n+5],m[o+10]=g[n+6],m[o+11]=g[n+7],m[o+12]=g[n+8],m[o+13]=g[n+9],m[o+14]=g[n+10],m[o+15]=g[n+11],m[o+16]=g[n+8],m[o+17]=g[n+9],m[o+18]=g[n+10],m[o+19]=g[n+11],m[o+20]=g[n],m[o+21]=g[n+1],m[o+22]=g[n+2],m[o+23]=g[n+3]);f.needsUpdate=!0,p&&(l.geometry.attributes.color.needsUpdate=!0)}}function d(b){var c,d,e,f,g,h,i,j=a.color_map,k=[];for(b.forEach(function(a){k.push(j.mapColors(a.values,{min:a.range_min,max:a.range_max,alpha:a.alpha}))}),c=new Float32Array(k[0].length),d=0,h=k[0].length/4;h>d;d++)for(e=0,g=k.length;g>e;e++)f=4*d,i=k[e][f+3],c[f]+=k[e][f]*i,c[f+1]+=k[e][f+1]*i,c[f+2]+=k[e][f+2]*i,c[f+3]+=i;return c}var e=null;a.updateColors=function(f,g){function h(b){var d,e=a.model.getObjectByName(f.apply_to_shape,!0);d=e?[e]:a.model.children,c(b,d),BrainBrowser.events.triggerEvent("updatecolors",b),j&&j()}g=g||{};var i=g.blend,j=g.complete;clearTimeout(e),e=setTimeout(function(){i?h(d(f)):b(f,g.model_name,h)},0)},a.setIntensityRange=function(b,c,d){d=d||{};var e=a.model_data.get(d.model_name).intensity_data;e.range_min=b,e.range_max=c,a.updateColors(e,{complete:d.complete}),BrainBrowser.events.triggerEvent("rangechange",e)},a.blend=function(b){var c,d=a.blend_data,e=d.length;for(d[0].alpha=b,d[1].alpha=1-b,c=2;e>c;c++)d[c].alpha=0;a.updateColors(d,{blend:!0})}},BrainBrowser.SurfaceViewer.modules.loading=function(a){"use strict";function b(a,b,c){c=c||{};var d=c.format||"mniobj",g=c.parse||{};e(a,d,g,function(a){BrainBrowser.loader.checkCancel(c.cancel)||f(a,b,c)})}function c(b,c,d){d=d||{};var e=d.name||c,f=d.format||"mniobj",g=a.model_data.get(d.model_name),h=1===d.blend_index?d.blend_index:0,i=1-h,j={};a.getAttribute("fix_color_range")&&g.intensity_data&&(j={min:g.intensity_data.range_min,max:g.intensity_data.range_max}),a.blend_data=a.blend_data||[],l.parseIntensityData(b,f,function(b){var c,f;a.getAttribute("fix_color_range")&&void 0!==j.min&&void 0!==j.max?(c=j.min,f=j.max):(c=void 0===d.min?b.min:d.min,f=void 0===d.max?b.max:d.max),b.filename=e,b.apply_to_shape=d.apply_to_shape,b.applied=!1,g.intensity_data=b,a.blend_data[h]=b,b.range_min=c,b.range_max=f,a.blend_data[i]&&a.blend_data[i].applied?(a.blend_data[i].range_min=BrainBrowser.utils.min(a.blend_data[i].values),a.blend_data[i].range_max=BrainBrowser.utils.max(a.blend_data[i].values),a.blend(.5),BrainBrowser.events.triggerEvent("loadintensitydata",a.blend_data),BrainBrowser.events.triggerEvent("blendcolormaps",b.range_min,b.range_max,b)):(BrainBrowser.events.triggerEvent("loadintensitydata",b),a.updateColors(b,{complete:d.complete})),b.applied=!0})}function d(b,c,d){d=d||{};var e=a.model_data.get(d.model_name);a.color_map=b,BrainBrowser.events.triggerEvent("loadcolormap",b),e&&e.intensity_data&&a.updateColors(e.intensity_data,{filename:c})}function e(a,b,c,d){var e,f=b+"_model";if(!l.worker_urls[f])throw e="error in SurfaceViewer configuration.\nModel worker URL for "+b+" not defined.\nUse 'BrainBrowser.config.set(\"model_types."+b+".worker\", ...)' to set it.",BrainBrowser.events.triggerEvent("error",e),new Error(e);var g,h=new Worker(l.worker_urls[f]);h.addEventListener("message",function(a){var f=a.data;if(f.error)throw e="error parsing model.\n"+f.error_message+"\nFile type: "+b+"\nOptions: "+JSON.stringify(c),BrainBrowser.events.triggerEvent("error",e),new Error(e);d&&(g=new Worker(l.worker_urls.deindex),g.addEventListener("message",function(a){d(a.data)}),g.postMessage(f)),h.terminate()}),h.postMessage({data:a,options:c})}function f(b,c,d){d=d||{};var e=d.render_depth,f=d.complete;g(b,c,e),BrainBrowser.events.triggerEvent("displaymodel",a.model),f&&f()}function g(b,c,d){var e,f,g,i,k=a.model,l=b.shapes,m=b.name||c,n="line"===b.type;if(j(m,b),l){for(g=0,i=l.length;i>g;g++)f=b.shapes[g],e=h(f,n),e.model_name=m,e.name=f.name||c+"_"+(g+1),e.geometry.original_data={vertices:b.vertices,indices:f.indices,normals:b.normals,colors:b.colors},d&&(e.renderDepth=d),k.add(e);b.split&&(k.children[0].name="left",k.children[0].model_num=0,k.children[1].name="right",k.children[1].model_num=1)}}function h(a,b){var c,d,e=a.unindexed,f=a.wireframe,g=a.centroid,h=e.position,j=e.normal||[],k=e.color||[],l=new THREE.BufferGeometry;return l.dynamic=!0,l.attributes.position={itemSize:3,array:new Float32Array(h),numItems:h.length},j.length>0?l.attributes.normal={itemSize:3,array:new Float32Array(j)}:l.computeVertexNormals(),k.length>0&&(l.attributes.color={itemSize:4,array:new Float32Array(k)}),b?(c=new THREE.LineBasicMaterial({vertexColors:THREE.VertexColors}),d=new THREE.Line(l,c,THREE.LinePieces)):(c=new THREE.MeshPhongMaterial({color:16777215,ambient:16777215,specular:1052688,shininess:150,vertexColors:THREE.VertexColors}),d=new THREE.Mesh(l,c),d.add(i(d,f))),d.centroid=g,d.position.set(g.x,g.y,g.z),d}function i(a,b){var c,d,e=new THREE.BufferGeometry;return e.attributes.position={itemSize:3,array:b.position,numItems:b.position.length},e.attributes.color={itemSize:4,array:b.color},e.attributes.color.needsUpdate=!0,c=new THREE.LineBasicMaterial({vertexColors:THREE.VertexColors}),d=new THREE.Line(e,c,THREE.LinePieces),d.name="__WIREFRAME__",d.visible=!1,a.wireframe_active=!1,d}function j(a,b){n[a]=b}function k(){n={}}var l=BrainBrowser.SurfaceViewer,m=BrainBrowser.loader,n={};a.model_data={get:function(a){return a=a||Object.keys(n)[0],n[a]||null},forEach:function(a){Object.keys(n).forEach(function(b){a(n[b],b)})}},a.loadModelFromURL=function(a,c){m.loadFromURL(a,b,c)},a.loadModelFromFile=function(a,c){m.loadFromFile(a,b,c)},a.loadIntensityDataFromURL=function(a,b){m.loadFromURL(a,c,b)},a.loadIntensityDataFromFile=function(a,b){m.loadFromFile(a,c,b)},a.loadColorMapFromURL=function(a,b){m.loadColorMapFromURL(a,d,b)},a.loadColorMapFromFile=function(a,b){m.loadColorMapFromFile(a,d,b)},a.clearScreen=function(){for(var b=a.model.children;b.length>0;)a.model.remove(b[0]);k(),a.resetView(),BrainBrowser.events.triggerEvent("clearscreen")}},BrainBrowser.SurfaceViewer.modules.rendering=function(a){"use strict";function b(e){var h,j,k=a.model;window.requestAnimationFrame(b),d=c||e,c=e,h=c-d,j=15e-5*h,a.autorotate.x&&(k.rotation.x+=j),a.autorotate.y&&(k.rotation.y+=j),a.autorotate.z&&(k.rotation.z+=j),i.render(f,g)}var c,d,e=new THREE.WebGLRenderer({preserveDrawingBuffer:!0}),f=new THREE.Scene,g=new THREE.PerspectiveCamera(30,a.dom_element.offsetWidth/a.dom_element.offsetHeight,1,3e3),h=new THREE.PointLight(16777215),i=e,j={},k=e.domElement;a.model=new THREE.Object3D,f.add(a.model),a.render=function(){var c=a.dom_element;e.setClearColor(0),e.setSize(c.offsetWidth,c.offsetHeight),c.appendChild(e.domElement),g.position.z=500,h.position.set(0,0,500),f.add(h),a.autorotate={},window.onresize=function(){i.setSize(c.offsetWidth,c.offsetHeight),g.aspect=c.offsetWidth/c.offsetHeight,g.updateProjectionMatrix()},window.onresize(),b()},a.canvasDataURL=function(){return e.domElement.toDataURL()},a.addEffect=function(b){var c;BrainBrowser.utils.isFunction(THREE[b])&&(c=new THREE[b](e),c.setSize(a.dom_element.offsetWidth,a.dom_element.offsetHeight),j[b]=c)},a.setEffect=function(a){i=j[a]?j[a]:e},a.setCameraPosition=function(a,b,c){g.position.set(a,b,c),h.position.set(a,b,c)},a.resetView=function(){var b,c,d,e,f=a.model,i=new THREE.Matrix4;for(i.getInverse(f.matrix),f.applyMatrix(i),g.position.set(0,0,500),h.position.set(0,0,500),d=0,e=a.model.children.length;e>d;d++)b=f.children[d],b.centroid?b.position.set(b.centroid.x,b.centroid.y,b.centroid.z):b.position.set(0,0,0),b.rotation.set(0,0,0),c=b.getObjectByName("__WIREFRAME__")},a.zoom=function(a){var b=g.position,c=b.z/a;c>g.near&&c<.9*g.far&&(b.z=c,h.position.z=c)},a.setClearColor=function(a){e.setClearColor(a,1)},a.drawDot=function(b,c,d,e,g){e=e||2,e=e>=0?e:0,g=g>=0?g:16711680;var h=new THREE.SphereGeometry(e),i=new THREE.MeshBasicMaterial({color:g}),j=new THREE.Mesh(h,i);return j.position.set(b,c,d),a.model?a.model.add(j):f.add(j),j},a.pick=function(b,c){b=void 0===b?a.mouse.x:b,c=void 0===c?a.mouse.y:c,b=b/a.dom_element.offsetWidth*2-1,c=-c/a.dom_element.offsetHeight*2+1;var d,e,f,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x=a.model,y=new THREE.Projector,z=new THREE.Raycaster,A=new THREE.Vector3(b,c,g.near),B=null,C=new THREE.Matrix4;for(y.unprojectVector(A,g),z.set(g.position,A.sub(g.position).normalize()),d=z.intersectObject(x,!0),r=0;rr;r++)o=n[i[r]],p=new THREE.Vector3(m[3*o],m[3*o+1],m[3*o+2]),q=h.distanceTo(new THREE.Vector3(p.x-u,p.y-v,p.z-w)),l>q&&(j=o,k=p,l=q);e={index:j,point:k,object:f}}else e=null;return e},function(){function b(a,b){var c,d,e=new THREE.Matrix4,f=a.x,i=a.y;if(null!==n)if(c=f-n,d=i-o,"rotate"===m){e.getInverse(l.matrix);var j=new THREE.Vector3(1,0,0).applyMatrix4(e).normalize();l.rotateOnAxis(j,d/150),e.getInverse(l.matrix),j=new THREE.Vector3(0,1,0).applyMatrix4(e).normalize(),l.rotateOnAxis(j,c/150)}else b=b||1,b*=g.position.z/500,g.position.x-=c*b*.25,h.position.x-=c*b*.25,g.position.y+=d*b*.25,h.position.y+=d*b*.25;n=f,o=i}function c(){var b,c=a.touches[0].x-a.touches[1].x,d=a.touches[0].y-a.touches[1].y,e=Math.sqrt(c*c+d*d);null!==p&&(b=e-p,a.zoom(1+.01*b)),p=e}function d(c){c.preventDefault(),c.stopPropagation(),b(a.mouse,1.1)}function e(d){d.preventDefault(),d.stopPropagation(),"zoom"===m?c():b(a.touches[0],2)}function f(){document.removeEventListener("mousemove",d,!1),document.removeEventListener("mouseup",f,!1),n=null,o=null}function i(){document.removeEventListener("touchmove",e,!1),document.removeEventListener("touchend",i,!1),n=null,o=null,p=null}function j(b){var c=Math.max(-1,Math.min(1,b.wheelDelta||-b.detail));b.preventDefault(),b.stopPropagation(),a.zoom(1+.05*c)}var l=a.model,m="rotate",n=null,o=null,p=null;k.addEventListener("mousedown",function(a){document.addEventListener("mousemove",d,!1),document.addEventListener("mouseup",f,!1),m=1===a.which?"rotate":"translate"},!1),k.addEventListener("touchstart",function(a){document.addEventListener("touchmove",e,!1),document.addEventListener("touchend",i,!1),m=1===a.touches.length?"rotate":2===a.touches.length?"zoom":"translate"},!1),k.addEventListener("mousewheel",j,!1),k.addEventListener("DOMMouseScroll",j,!1),k.addEventListener("contextmenu",function(a){a.preventDefault(),a.stopPropagation()},!1)}()},BrainBrowser.SurfaceViewer.modules.views=function(a){"use strict";function b(a){return a*Math.PI/180}var c={medialView:function(c){var d=a.model;c.split&&(d.getObjectByName("left").position.x-=100,d.getObjectByName("left").rotation.z-=b(90),d.getObjectByName("right").position.x+=100,d.getObjectByName("right").rotation.z+=b(90),d.rotation.x+=b(-90))},lateralView:function(c){var d,e,f=a.model;c.split&&(d=f.getObjectByName("left"),e=f.getObjectByName("right"),d.position.x-=100,d.rotation.z+=b(-90),e.position.x+=100,e.rotation.z+=b(90),f.rotation.x+=b(90),f.rotation.y+=b(180))},inferiorView:function(){a.model.rotation.y+=b(180)},anteriorView:function(){a.resetView(),a.model.rotation.x+=b(-90),a.model.rotation.z+=b(180)},posteriorView:function(){a.resetView(),a.model.rotation.x+=b(-90)}};a.setTransparency=function(b,c){c=c||{};var d,e,f,g=c.shape_name,h=a.model.getObjectByName(g);d=h?[h]:a.model.children||[],d.forEach(function(a){e=a.material,e.opacity=b,e.transparent=1===b?!1:!0,f=a.getObjectByName("__WIREFRAME__"),f&&(f.material.opacity=e.opacity,f.material.transparent=e.transparent)})},a.setWireframe=function(b,c){c=c||{};var d,e,f=c.shape_name,g=a.model.getObjectByName(f);d=g?[g]:a.model.children||[],d.forEach(function(a){e=a.getObjectByName("__WIREFRAME__"),e&&(a.visible=!b,e.visible=b,a.wireframe_active=b)})},a.setView=function(b,d){var e=b+"View",f=a.model_data.get(d);a.resetView(),f&&BrainBrowser.utils.isFunction(c[e])&&c[e](f)},a.separateHalves=function(b,c){b=b||1,c=c||{},a.model_data.get(c.model_name).split&&(a.model.children[0].position.x-=b,a.model.children[1].position.x+=b)}}; \ No newline at end of file diff --git a/build/brainbrowser-2.0.1/brainbrowser.volume-viewer.min.js b/build/brainbrowser-2.0.1/brainbrowser.volume-viewer.min.js new file mode 100644 index 00000000..a6cc1078 --- /dev/null +++ b/build/brainbrowser-2.0.1/brainbrowser.volume-viewer.min.js @@ -0,0 +1,29 @@ +/* +* BrainBrowser: Web-based Neurological Visualization Tools +* (https://brainbrowser.cbrain.mcgill.ca) +* +* Copyright (C) 2011 +* The Royal Institution for the Advancement of Learning +* McGill University +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +*/ + +/* +* BrainBrowser v2.0.1 +* +* Author: Tarek Sherif (http://tareksherif.ca/) +* Author: Nicolas Kassis +*/ +!function(){"use strict";var a="2.0.1";a=a.indexOf("BRAINBROWSER_VERSION")>0?"D.E.V":a,window.BrainBrowser={version:a},window.requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){return window.setTimeout(a,1e3/60)},window.cancelAnimationFrame=window.cancelAnimationFrame||function(a){window.clearTimeout(a)}}(),function(){"use strict";function a(b,c,d,e){return c>d?e(b):void Object.keys(b).forEach(function(f){a(b[f],c+1,d,e)})}BrainBrowser.createTreeStore=function(){var b={};return{set:function(){var a,c,d,e,f=arguments[arguments.length-1],g=Array.prototype.slice.call(arguments,0,arguments.length-1),h=b;for(c=0,d=g.length-1;d>c;c++){if(a=g[c],h[a]&&"object"!=typeof h[a])throw e="Hash key '["+g.slice(0,c+1).join("][")+"]' has already been set to a non-object value.\nCannot set '["+g.join("][")+"]'",BrainBrowser.events.triggerEvent("error",e),new Error(e);h[a]||(h[a]={}),h=h[a]}a=g[c],h[a]=f},get:function(){var a,c,d,e=Array.prototype.slice.call(arguments),f=b;if(0===e.length)return b;for(c=0,d=e.length-1;d>c;c++){if(a=e[c],void 0===f[a])return null;f=f[a]}return a=e[c],void 0!==f[a]?f[a]:null},remove:function(){var a,c,d,e,f=Array.prototype.slice.call(arguments),g=b;for(c=0,d=f.length-1;d>c;c++){if(a=f[c],void 0===g[a])return null;g=g[a]}return a=f[c],e=g[a],g[a]=void 0,e},reset:function(a){a=a&&"object"==typeof a?a:{},b=a},forEach:function(c,d){c=c>0?c:1,a(b,1,c,d)}}}}(),function(){"use strict";BrainBrowser.createColorMap=function(a){function b(a,b,d,e){var f,g,h,i=document.createElement("canvas"),j=new Array(256);for(i.width=256,i.height=d,f=0;256>f;f++)e?j[255-f]=f:j[f]=f;for(a=c.mapColors(j,{scale255:!0}),h=i.getContext("2d"),g=0;256>g;g++)h.fillStyle="rgb("+Math.floor(a[4*g])+", "+Math.floor(a[4*g+1])+", "+Math.floor(a[4*g+2])+")",h.fillRect(g,0,1,b);return i}var c={createCanvasWithScale:function(a,d,e){e=e||{};var f,g,h=c.colors,i=e.flip,j=d-a;return f=b(h,20,40,i),g=f.getContext("2d"),g.fillStyle="#FFA000",g.fillRect(.5,20,1,10),g.fillText(a.toPrecision(3),.5,40),g.fillRect(f.width/4,20,1,10),g.fillText((a+.25*j).toPrecision(3),.25*f.width,40),g.fillRect(f.width/2,20,1,10),g.fillText((a+.5*j).toPrecision(3),.5*f.width,40),g.fillRect(3*f.width/4,20,1,10),g.fillText((a+.75*j).toPrecision(3),.75*f.width,40),g.fillRect(f.width-.5,20,1,10),g.fillText(d.toPrecision(3),f.width-20,40),f},mapColors:function(a,b){b=b||{};var d,e,f,g,h=void 0===b.min?0:b.min,i=void 0===b.max?255:b.max,j=void 0===b.scale255?!1:b.scale255,k=void 0===b.brightness?0:b.brightness,l=void 0===b.contrast?1:b.contrast,m=void 0===b.alpha?1:b.alpha,n=b.destination||[],o=c.colors,p=o.length,q=i-h,r=(q+q/p)/p,s=j?255:1,t=[];for(m*=s,d=0,e=a.length;e>d;d++)g=a[d],f=h>=g?0:a[d]>i?p-1:Math.floor((g-h)/r),t=o[f]||[0,0,0],n[4*d+0]=s*(t[0]*l+k),n[4*d+1]=s*(t[1]*l+k),n[4*d+2]=s*(t[2]*l+k),n[4*d+3]=m;return n}};return function(){if(a){a=a.replace(/^\s+/,"").replace(/\s+$/,"");var b,d,e,f,g,h=a.split(/\n/),i=[];for(b=0,e=h.length;e>b;b++)if(g=h[b].replace(/^\s+/,"").replace(/\s+$/,"").split(/\s+/).slice(0,4),f=g.length,!(3>f)){for(d=0;f>d;d++)g[d]=parseFloat(g[d]);4>f&&g.push(1),i.push(g)}c.colors=i}}(),c}}(),function(){"use strict";var a=BrainBrowser.createTreeStore();BrainBrowser.config={set:function(b,c){b=b||"";var d=b.split(".");d.push(c),a.set.apply(a,d)},get:function(b){b=b||"";var c=b.split(".");return a.get.apply(a,c)}}}(),function(){"use strict";var a=[];BrainBrowser.events={addEventListener:function(b,c){a[b]||(a[b]=[]),a[b].push(c)},triggerEvent:function(b){var c=Array.prototype.slice.call(arguments,1);a[b]&&a[b].forEach(function(a){setTimeout(function(){a.apply(null,c)},0)})}}}(),function(){"use strict";var a=BrainBrowser.loader={loadFromURL:function(b,c,d){d=d||{};var e,f=new XMLHttpRequest,g=d.result_type,h=b.split("/"),i=h[h.length-1];f.open("GET",b),"arraybuffer"===g&&(f.responseType="arraybuffer"),f.onreadystatechange=function(){if(4===f.readyState){if(e=f.status,!(e>=200&&300>e||304===e)){var g="error loading URL: "+b+"\nHTTP Response: "+f.status+"\nHTTP Status: "+f.statusText+"\nResponse was: \n"+f.response;throw BrainBrowser.events.triggerEvent("error",g),new Error(g)}a.checkCancel(d)||c(f.response,i,d)}},f.send()},loadFromFile:function(a,b,c){var d=a.files;if(0!==d.length){c=c||{};var e=c.result_type,f=new FileReader,g=a.value.split("\\"),h=g[g.length-1];f.file=d[0],f.onloadend=function(a){b(a.target.result,h,c)},f.onerror=function(){var a="error reading file: "+h;throw BrainBrowser.events.triggerEvent("error",a),new Error(a)},"arraybuffer"===e?f.readAsArrayBuffer(d[0]):f.readAsText(d[0])}},loadColorMapFromURL:function(a,b,c){BrainBrowser.loader.loadFromURL(a,function(a,c,d){b(BrainBrowser.createColorMap(a),c,d)},c)},loadColorMapFromFile:function(a,b,c){BrainBrowser.loader.loadFromFile(a,function(a,c,d){b(BrainBrowser.createColorMap(a),c,d)},c)},checkCancel:function(a){a=a||{},BrainBrowser.utils.isFunction(a)&&(a={test:a});var b=a.test,c=a.cleanup,d=!1;return b&&b()&&(d=!0,c&&c()),d}}}(),function(){"use strict";BrainBrowser.utils={canvasEnabled:function(){return!!document.createElement("canvas")},webglEnabled:function(){var a=document.createElement("canvas");try{return!(!a||!window.WebGLRenderingContext||!a.getContext("webgl")&&!a.getContext("experimental-webgl"))}catch(b){return!1}},webWorkersEnabled:function(){return!!window.Worker},webGLErrorMessage:function(){var a,b='BrainBrowser requires WebGL.
';return b+=window.WebGLRenderingContext?"Your browser seems to support it, but it is
disabled or unavailable.
":"Your browser does not seem to support it.
",b+='Test your browser\'s WebGL support here.',a=document.createElement("div"),a.id="webgl-error",a.innerHTML=b,a},isFunction:function(a){return a instanceof Function||"function"==typeof a},isNumeric:function(a){return!isNaN(parseFloat(a))},min:function(){var a=Array.prototype.slice.call(arguments);a=1===a.length&&Array.isArray(a[0])?a[0]:a;var b,c,d=a[0];for(b=1,c=a.length;c>b;b++)a[b]b;b++)a[b]>d&&(d=a[b]);return d},getOffset:function(a){for(var b=0,c=0;a.offsetParent;)b+=a.offsetTop,c+=a.offsetLeft,a=a.offsetParent;return{top:b,left:c}},captureMouse:function(a){var b={x:0,y:0,left:!1,middle:!1,right:!1};return document.addEventListener("mousemove",function(c){var d,e,f=BrainBrowser.utils.getOffset(a);void 0!==c.pageX?(d=c.pageX,e=c.pageY):(d=c.clientX+window.pageXOffset,e=c.clientY+window.pageYOffset),b.x=d-f.left,b.y=e-f.top},!1),a.addEventListener("mousedown",function(a){a.preventDefault(),0===a.button&&(b.left=!0),1===a.button&&(b.middle=!0),2===a.button&&(b.right=!0)},!1),a.addEventListener("mouseup",function(a){a.preventDefault(),0===a.button&&(b.left=!1),1===a.button&&(b.middle=!1),2===a.button&&(b.right=!1)},!1),a.addEventListener("mouseleave",function(a){a.preventDefault(),b.left=b.middle=b.right=!1},!1),a.addEventListener("contextmenu",function(a){a.preventDefault()},!1),b},captureTouch:function(a){function b(b){var d,e,f,g,h,i=BrainBrowser.utils.getOffset(a);for(c.length=g=b.touches.length,f=0;g>f;f++)h=b.touches[f],void 0!==h.pageX?(d=h.pageX,e=h.pageY):(d=h.clientX+window.pageXOffset,e=h.clientY+window.pageYOffset),c[f]=c[f]||{},c[f].x=d-i.left,c[f].y=e-i.top}var c=[];return a.addEventListener("touchstart",b,!1),a.addEventListener("touchmove",b,!1),a.addEventListener("touchend",b,!1),c}}}(),function(){"use strict";var a=BrainBrowser.VolumeViewer={};a.modules={},a.volume_loaders={},a.start=function(b,c){function d(b,c,d){var e=a.utils.axis_to_number[c],g=f.volumes[b],h=g.display[e];h.setSlice(d),h.updateCursor()}function e(){document.addEventListener("keydown",function(b){if(f.active_canvas){var c,d,e=f.active_canvas,g=b.which,h=e.getAttribute("data-volume-id"),i=f.volumes[h],j=e.getAttribute("data-axis-name"),k=a.utils.axis_to_number[j],l=i.display[a.utils.axis_to_number[j]],m={16:function(){var a=l.mouse.x,b=l.mouse.y;(l.mouse.left||l.mouse.middle||l.mouse.right)&&(l.last_position.x=a,l.last_position.y=b,f.synced&&f.volumes.forEach(function(c,d){if(d!==h){var e=c.display[k];e.last_position.x=a,e.last_position.y=b}}))},17:function(){l.anchor||(l.mouse.left||l.mouse.middle||l.mouse.right)&&(l.anchor={x:l.mouse.x,y:l.mouse.y})},37:function(){c=l.slice.width_space.name,i.position[c]>0&&i.position[c]--},38:function(){c=l.slice.height_space.name,i.position[c]0&&i.position[c]--}};return"function"==typeof m[g]?(b.preventDefault(),m[g](),l.updateCursor(),f.redrawVolume(h),f.synced&&f.volumes.forEach(function(a,b){b!==h&&f.setCursor(b,j,l.cursor)}),!1):32===g&&(b.preventDefault(),i.data.time)?(d=b.shiftKey?Math.max(0,i.current_time-1):Math.min(i.current_time+1,i.data.time.space_length-1),i.current_time=d,f.synced&&f.volumes.forEach(function(a,c){c!==h&&(a.current_time=b.shiftKey?Math.max(0,Math.min(d,a.data.time.space_length-1)):Math.max(0,Math.min(d,a.data.time.space_length-1)))}),f.redrawVolumes(),!1):void 0}},!1),document.addEventListener("keyup",function(a){var b=a.which,c={17:function(){f.volumes.forEach(function(a){a.display.forEach(function(a){a.anchor=null})})}};return"function"==typeof c[b]?(a.preventDefault(),c[b](),!1):void 0},!1)}var f={dom_element:document.getElementById(b),volumes:[],synced:!1,panel_width:256,panel_height:256};Object.keys(a.modules).forEach(function(b){a.modules[b](f)}),console.log("BrainBrowser Volume Viewer v"+BrainBrowser.version);var g={};return f.fetchSlice=function(b,c,e,h){g[b]=g[b]||{},clearTimeout(g[b][c]),g[b][c]=setTimeout(function(){var g,i=f.volumes[b],j=a.utils.axis_to_number[c];void 0!==e&&(i.position[c]=e),g=i.slice(c),g.vol_id=b,g.axis_number=j,g.min=i.min,g.max=i.max,d(b,c,g),BrainBrowser.events.triggerEvent("sliceupdate",b,c,g),BrainBrowser.utils.isFunction(h)&&h(g)},0)},f.setPanelSize=function(a,b,c){c=c||{};var d,e,g,h=c.scale_image;h&&(d=f.panel_width,e=f.panel_height,g=Math.min(a/d,b/e)),f.panel_width=a>0?a:f.panel_width,f.panel_height=b>0?b:f.panel_height,f.volumes.forEach(function(d,e){d.display.forEach(function(d,i){d.setSize(f.panel_width,f.panel_height,c),h&&(d.zoom=d.zoom*g,d.image_center.x=a/2,d.image_center.y=b/2,f.setCursor(e,["xspace","yspace","zspace"][i],{x:d.image_center.x,y:d.image_center.y}))})}),h&&f.redrawVolumes()},e(),c(f),f}}(),function(){"use strict";var a={setSize:function(a,b){this.canvas.width=a,this.canvas.height=b},setSlice:function(a){this.slice=a,this.slice_image=this.slice.getImage(this.zoom)},refreshSliceImage:function(){this.slice_image=this.slice.getImage(this.zoom)},updateCursor:function(){var a=this.volume,b=this.slice,c=this.getImageOrigin();this.cursor.x=a.position[b.width_space.name]*Math.abs(b.width_space.step)*this.zoom+c.x,this.cursor.y=(b.height_space.space_length-a.position[b.height_space.name])*Math.abs(b.height_space.step)*this.zoom+c.y},followPointer:function(a){var b=a.x-this.last_position.x,c=a.y-this.last_position.y;this.image_center.x+=b,this.image_center.y+=c,this.cursor.x+=b,this.cursor.y+=c,this.last_position.x=a.x,this.last_position.y=a.y},reset:function(){this.zoom=1,this.image_center.x=this.canvas.width/2,this.image_center.y=this.canvas.height/2},getImageOrigin:function(){return{x:this.image_center.x-this.slice_image.width/2,y:this.image_center.y-this.slice_image.height/2}},drawSlice:function(){var a,b=this.slice_image;b&&(a=this.getImageOrigin(),this.context.putImageData(b,a.x,a.y))},drawCursor:function(a){var b,c,d,e,f,g,h=this.context,i=this.zoom,j=8*i;a=a||"#FF0000",h.save(),h.strokeStyle=a,h.fillStyle=a,d=i,b=this.cursor.x-d,c=this.cursor.y-d,h.lineWidth=2*d,h.beginPath(),h.moveTo(b,c-j),h.lineTo(b,c-d),h.moveTo(b,c+d),h.lineTo(b,c+j),h.moveTo(b-j,c),h.lineTo(b-d,c),h.moveTo(b+d,c),h.lineTo(b+j,c),h.stroke(),this.anchor&&(f=(this.anchor.x-this.cursor.x)/this.zoom,g=(this.anchor.y-this.cursor.y)/this.zoom,e=Math.sqrt(f*f+g*g),h.font="bold 12px arial",this.canvas.width-this.cursor.x<50?(h.textAlign="right",b=this.cursor.x-j):(h.textAlign="left",b=this.cursor.x+j),this.cursor.y<30?(h.textBaseline="top",c=this.cursor.y+j):(h.textBaseline="bottom",c=this.cursor.y-j),h.fillText(e.toFixed(2),b,c),h.lineWidth=1,h.beginPath(),h.arc(this.anchor.x,this.anchor.y,2*d,0,2*Math.PI),h.fill(),h.moveTo(this.anchor.x,this.anchor.y),h.lineTo(this.cursor.x,this.cursor.y),h.stroke()),h.restore()}};BrainBrowser.VolumeViewer.createPanel=function(b){b=b||{};var c={cursor:{x:0,y:0},last_position:{x:0,y:0},image_center:{x:0,y:0},zoom:1},d=Object.create(a);return Object.keys(c).forEach(function(a){d[a]=c[a]}),Object.keys(b).forEach(function(a){d[a]=b[a]}),d.canvas&&BrainBrowser.utils.isFunction(d.canvas.getContext)&&(d.context=d.canvas.getContext("2d"),d.mouse=BrainBrowser.utils.captureMouse(d.canvas),d.touches=BrainBrowser.utils.captureTouch(d.canvas)),d}}(),function(){"use strict";function a(a,b,c,d,e,f){var g,h,i,j,k,l=[];for(f=f||1,g=0;b>g;g++)for(h=0;c>h;h++)for(j=d?b-g-1:g,k=e?c-h-1:h,i=0;f>i;i++)l[(h*b+g)*f+i]=a[(k*b+j)*f+i];return l}BrainBrowser.VolumeViewer.utils={axis_to_number:{xspace:0,yspace:1,zspace:2},nearestNeighbor:function(b,c,d){var e=b.data,f=b.width,g=b.height,h=document.createElement("canvas").getContext("2d"),i=4;if(f===c&&g===d)return b;0>c&&d>0&&(e=a(e,f,g,!0,!1,i)),c=Math.abs(c),d=Math.abs(d);for(var j=h.createImageData(c,d),k=j.data,l=f/c,m=g/d,n=0;d>n;n++)for(var o=0;c>o;o++)for(var p=Math.floor(o*l),q=Math.floor(n*m),r=0;i>r;r++)k[Math.floor(n*c+o)*i+r]=e[Math.floor(q*f+p)*i+r];return j},rotateUint16Array90Left:function(a,b,c){var d,e,f=new Uint16Array(b*c);for(d=0;b>d;d++)for(e=0;c>e;e++)f[d*c+e]=a[e*b+(b-d)];return f},rotateUint16Array90Right:function(a,b,c){var d,e,f=new Uint16Array(b*c);for(d=0;b>d;d++)for(e=0;c>e;e++)f[d*c+e]=a[(c-e)*b+d];return f}}}(),BrainBrowser.VolumeViewer.modules.loading=function(a){"use strict";function b(a,b){var c,d=h.volume_loaders[a.type];if(!d)throw c="Unsuported Volume Type",BrainBrowser.events.triggerEvent("error",c),new Error(c);d(a,b)}function c(c,d,e){b(d,function(b){var f=0;a.volumes[c]=b,b.display=g(a.dom_element,c,d),b.color_map=a.default_color_map,["xspace","yspace","zspace"].forEach(function(d){var g=b.position[d]=Math.floor(b.header[d].space_length/2);a.fetchSlice(c,d,g,function(){3===++f&&BrainBrowser.utils.isFunction(e)&&e(b)})})})}function d(b,c,d){b.cursor_color=c,a.default_color_map=b,BrainBrowser.utils.isFunction(d)&&d(b)}function e(b,c,d,e){c.cursor_color=d,a.setVolumeColorMap(b,c),BrainBrowser.utils.isFunction(e)&&e(a.volumes[b],c)}function f(a,b,c,d){var e=document.getElementById(c).innerHTML.replace(/\{\{VOLID\}\}/gm,b),f=document.createElement("div");f.innerHTML=e;var g,h,i,j=f.childNodes,k=f.getElementsByClassName(d)[0];for(g=0,h=a.childNodes.length;h>g;g++)i=a.childNodes[g],1===i.nodeType&&(k.appendChild(i),g--,h--);return j}function g(b,c,d){var e,g=document.createElement("div"),i=a.volumes[c],j=[],k=d.template||{};if(g.classList.add("volume-container"),["xspace","yspace","zspace"].forEach(function(b){var d=document.createElement("canvas");d.width=a.panel_width,d.height=a.panel_height,d.setAttribute("data-volume-id",c),d.setAttribute("data-axis-name",b),d.classList.add("slice-display"),d.style.backgroundColor="#000000",g.appendChild(d),j.push(h.createPanel({volume:i,axis:b,canvas:d,cursor:{x:d.width/2,y:d.height/2},image_center:{x:d.width/2,y:d.height/2}}))}),k.element_id&&k.viewer_insert_class&&(e=f(g,c,k.element_id,k.viewer_insert_class),"function"==typeof k.complete&&k.complete(i,e),Array.prototype.forEach.call(e,function(a){1===a.nodeType&&g.appendChild(a)})),a.volumeUIControls){var l=document.createElement("div");l.className="volume-viewer-controls volume-controls",a.volumeUIControls.defer_until_page_load?BrainBrowser.events.addEventListener("ready",function(){g.appendChild(l),a.volumeUIControls(l,i,c)}):(a.volumeUIControls(l,i,c),g.appendChild(l))}return function(){var b=null;["xspace","yspace","zspace"].forEach(function(d,e){function f(b,f,g){var h={x:b.x,y:b.y};g&&(a.volumes.forEach(function(a){a.display.forEach(function(a){a.anchor=null})}),q.anchor={x:b.x,y:b.y}),f?(q.last_position.x=h.x,q.last_position.y=h.y,a.synced&&a.volumes.forEach(function(a,b){if(b!==c){var d=a.display[e];d.last_position.x=h.x,d.last_position.y=h.y}})):(a.setCursor(c,d,h),a.synced&&a.volumes.forEach(function(b,e){e!==c&&a.setCursor(e,d,h)}))}function g(b,f){var g={x:b.x,y:b.y};f?(q.followPointer(g),a.synced&&a.volumes.forEach(function(a,b){b!==c&&a.display[e].followPointer(g)})):(a.setCursor(c,d,g),a.synced&&a.volumes.forEach(function(b,e){e!==c&&a.setCursor(e,d,g)}))}function h(a){a.target===b&&(a.preventDefault(),a.stopPropagation(),g(q.mouse,a.shiftKey))}function i(a){a.target===b&&(a.preventDefault(),a.stopPropagation(),g(q.touches[0],3===q.touches.length))}function k(){document.removeEventListener("mousemove",h,!1),document.removeEventListener("mouseup",k,!1),a.volumes.forEach(function(a){a.display.forEach(function(a){a.anchor=null})}),b=null}function l(){document.removeEventListener("touchmove",i,!1),document.removeEventListener("touchend",l,!1),a.volumes.forEach(function(a){a.display.forEach(function(a){a.anchor=null})}),b=null}function m(){var a,b=q.touches[0].x-q.touches[1].x,c=q.touches[0].y-q.touches[1].y,d=Math.sqrt(b*b+c*c);null!==s&&(a=d-s,p(.2*a)),s=d}function n(){document.removeEventListener("touchmove",m,!1),document.removeEventListener("touchend",n,!1),s=null}function o(a){p(Math.max(-1,Math.min(1,a.wheelDelta||-a.detail)))}function p(b){event.preventDefault(),event.stopPropagation(),q.zoom=Math.max(q.zoom+.05*b,.05),a.fetchSlice(c,["xspace","yspace","zspace"][e]),a.synced&&a.volumes.forEach(function(d,f){if(f!==c){var g=d.display[e];g.zoom=Math.max(g.zoom+.05*b,.05),a.fetchSlice(f,["xspace","yspace","zspace"][e])}})}var q=j[e],r=q.canvas,s=null;r.addEventListener("mousedown",function(c){c.preventDefault(),c.stopPropagation(),a.active_canvas=b=c.target,document.addEventListener("mousemove",h,!1),document.addEventListener("mouseup",k,!1),f(q.mouse,c.shiftKey,c.ctrlKey)},!1),r.addEventListener("touchstart",function(c){c.preventDefault(),c.stopPropagation(),a.active_canvas=b=c.target,2===q.touches.length?(document.removeEventListener("touchmove",i,!1),document.removeEventListener("touchend",l,!1),document.addEventListener("touchmove",m,!1),document.addEventListener("touchend",n,!1)):(document.removeEventListener("touchmove",m,!1),document.removeEventListener("touchend",n,!1),document.addEventListener("touchmove",i,!1),document.addEventListener("touchend",l,!1),f(q.touches[0],3===q.touches.length,!0))},!1),r.addEventListener("mousewheel",o,!1),r.addEventListener("DOMMouseScroll",o,!1)})}(),b.appendChild(g),BrainBrowser.events.triggerEvent("volumeuiloaded",g,c),j}var h=BrainBrowser.VolumeViewer;a.loadVolumes=function(b){function d(d){c(d,g[d],function(){++j1?a.createOverlay(f,function(){BrainBrowser.utils.isFunction(i)&&i(),BrainBrowser.events.triggerEvent("volumesloaded")}):(BrainBrowser.utils.isFunction(i)&&i(),BrainBrowser.events.triggerEvent("volumesloaded")))})}b=b||{};var e,f=b.overlay&&"object"==typeof b.overlay?b.overlay:{},g=b.volumes,h=b.volumes.length,i=b.complete,j=0;for(e=0;h>e;e++)d(e)},a.loadVolumeColorMapFromURL=function(a,b,c,d){BrainBrowser.loader.loadColorMapFromURL(b,function(b){e(a,b,c,d)})},a.loadDefaultColorMapFromURL=function(a,b,c){BrainBrowser.loader.loadColorMapFromURL(a,function(a){d(a,b,c)})},a.loadVolumeColorMapFromFile=function(a,b,c,d){BrainBrowser.loader.loadColorMapFromFile(b,function(b){e(a,b,c,d)})},a.loadDefaultColorMapFromFile=function(a,b,c){BrainBrowser.loader.loadColorMapFromFile(a,function(a){d(a,b,c)})},a.setVolumeColorMap=function(b,c){a.volumes[b].color_map=c},a.loadVolume=function(b,d){c(a.volumes.length,b,d)},a.clearVolumes=function(){a.volumes=[],a.active_canvas=null,a.dom_element.innerHTML=""},a.createOverlay=function(b,c){b=b||{},a.loadVolume({volumes:a.volumes,type:"overlay",template:b.template},c)}},BrainBrowser.VolumeViewer.modules.rendering=function(a){"use strict";var b=BrainBrowser.VolumeViewer;a.draw=function(){var b,c,d,e=4,f=e/2;a.volumes.forEach(function(g){g.display.forEach(function(h){c=h.canvas,b=h.context,b.globalAlpha=255,b.clearRect(0,0,c.width,c.height),d=g.color_map||a.default_color_map,h.drawSlice(),h.drawCursor(d.cursor_color),c===a.active_canvas&&(b.save(),b.strokeStyle="#EC2121",b.lineWidth=e,b.strokeRect(f,f,c.width-e,c.height-e),b.restore())})})},a.render=function(){BrainBrowser.events.triggerEvent("rendering"),function b(){window.requestAnimationFrame(b),a.draw()}()},a.setCursor=function(c,d,e){var f,g,h=a.volumes[c],i=b.utils.axis_to_number[d],j=h.display[i],k=j.slice,l=j.getImageOrigin(),m=j.zoom;j.cursor.x=e.x,j.cursor.y=e.y,e?(f=Math.floor((e.x-l.x)/m/Math.abs(k.width_space.step)),g=Math.floor(k.height_space.space_length-(e.y-l.y)/m/Math.abs(k.height_space.step))):(f=null,g=null),a.fetchSlice(c,k.width_space.name,f),a.fetchSlice(c,k.height_space.name,g)},a.redrawVolume=function(b){var c=a.volumes[b];a.fetchSlice(b,"xspace",c.position.xspace),a.fetchSlice(b,"yspace",c.position.yspace),a.fetchSlice(b,"zspace",c.position.zspace)},a.redrawVolumes=function(){a.volumes.forEach(function(b,c){a.redrawVolume(c)})},a.resetDisplays=function(){a.volumes.forEach(function(a){a.display.forEach(function(a){a.reset()})})}},function(){"use strict";function a(a,b){var c,d;try{c=JSON.parse(a)}catch(e){throw d="server did not respond with valid JSON\nResponse was: \n"+a,BrainBrowser.events.triggerEvent("error",d),new Error(d)}BrainBrowser.utils.isFunction(b)&&b(c)}function b(a,b,d){var f=Object.create(e);f.position={},f.current_time=0,f.data=c(a,new Uint8Array(b)),f.header=f.data.header,f.min=0,f.max=255,BrainBrowser.utils.isFunction(d)&&d(f)}function c(a,b){var c,d,e,g,h,i,j=Object.create(f);j.header=a,j.order=a.order,4===j.order.length&&(j.order=j.order.slice(1),j.time=a.time),j.xspace=a.xspace,j.yspace=a.yspace,j.zspace=a.zspace,j.xspace.name="xspace",j.yspace.name="yspace",j.zspace.name="zspace",j.xspace.space_length=parseFloat(j.xspace.space_length),j.yspace.space_length=parseFloat(j.yspace.space_length),j.zspace.space_length=parseFloat(j.zspace.space_length),c=j.xspace.start=parseFloat(j.xspace.start),d=j.yspace.start=parseFloat(j.yspace.start),e=j.zspace.start=parseFloat(j.zspace.start),j.xspace.step=parseFloat(j.xspace.step),j.yspace.step=parseFloat(j.yspace.step),j.zspace.step=parseFloat(j.zspace.step),j.xspace.direction_cosines=j.xspace.direction_cosines||[1,0,0],j.yspace.direction_cosines=j.yspace.direction_cosines||[0,1,0],j.zspace.direction_cosines=j.zspace.direction_cosines||[0,0,1],g=j.xspace.direction_cosines=j.xspace.direction_cosines.map(parseFloat),h=j.yspace.direction_cosines=j.yspace.direction_cosines.map(parseFloat),i=j.zspace.direction_cosines=j.zspace.direction_cosines.map(parseFloat),j.voxel_origin={x:c*g[0]+d*h[0]+e*i[0],y:c*g[1]+d*h[1]+e*i[1],z:c*g[2]+d*h[2]+e*i[2]},4===j.order.length&&(j.time.space_length=parseFloat(j.time.space_length),j.time.start=parseFloat(j.time.start),j.time.step=parseFloat(j.time.step));var k=j[j.order[0]],l=j[j.order[1]],m=j[j.order[2]];return k.height=parseFloat(l.space_length),k.height_space=l,k.width=parseFloat(m.space_length),k.width_space=m,l.height=parseFloat(m.space_length),l.height_space=m,l.width=parseFloat(k.space_length),l.width_space=k,m.height=parseFloat(l.space_length),m.height_space=l,m.width=parseFloat(k.space_length),m.width_space=k,k.offset=parseFloat(l.space_length)*parseFloat(m.space_length),l.offset=parseFloat(k.space_length),m.offset=parseFloat(k.space_length),k.slice_length=k.height*k.width,j.cached_slices={},j.data=b,j}var d=BrainBrowser.VolumeViewer,e={slice:function(a,b,c){b=void 0===b?this.position[a]:b,c=void 0===c?this.current_time:c;var e=this.data.slice(a,b,c);return e.color_map=this.color_map,e.min=this.min,e.max=this.max,e.axis=a,e.getImage=function(a){a=a||1;var b=document.createElement("canvas").getContext("2d"),c=e.color_map,f=b.createImageData(e.width,e.height);c.mapColors(e.data,{min:e.min,max:e.max,scale255:!0,brightness:0,contrast:1,alpha:e.alpha,destination:f.data});var g=e.width_space.step,h=e.height_space.step;return d.utils.nearestNeighbor(f,Math.floor(e.width*g*a),Math.floor(e.height*h*a))},e},getVoxelCoords:function(){return{x:this.position.xspace,y:this.position.yspace,z:this.position.zspace}},setVoxelCoords:function(a,b,c){this.position.xspace=a,this.position.yspace=b,this.position.zspace=c},getWorldCoords:function(){return this.voxelToWorld(this.position.xspace,this.position.yspace,this.position.zspace)},setWorldCoords:function(a,b,c){var d=this.worldToVoxel(a,b,c);this.position.xspace=d.x,this.position.yspace=d.y,this.position.zspace=d.z},voxelToWorld:function(a,b,c){var d={};d[this.data.order[0]]=a,d[this.data.order[1]]=b,d[this.data.order[2]]=c,a=d.xspace,b=d.yspace,c=d.zspace;var e=this.data.xspace.direction_cosines,f=this.data.yspace.direction_cosines,g=this.data.zspace.direction_cosines,h=this.data.xspace.step,i=this.data.yspace.step,j=this.data.zspace.step,k=this.data.voxel_origin;return{x:a*e[0]*h+b*f[0]*i+c*g[0]*j+k.x,y:a*e[1]*h+b*f[1]*i+c*g[1]*j+k.y,z:a*e[2]*h+b*f[2]*i+c*g[2]*j+k.z}},worldToVoxel:function(a,b,c){var d=this.data.xspace.direction_cosines,e=this.data.yspace.direction_cosines,f=this.data.zspace.direction_cosines,g=this.data.xspace.step,h=this.data.yspace.step,i=this.data.zspace.step,j=this.data.voxel_origin,k=(-j.x*d[0]-j.y*d[1]-j.z*d[2])/g,l=(-j.x*e[0]-j.y*e[1]-j.z*e[2])/h,m=(-j.x*f[0]-j.y*f[1]-j.z*f[2])/i,n={x:Math.round(a*d[0]/g+b*d[1]/g+c*d[2]/g+k),y:Math.round(a*e[0]/h+b*e[1]/h+c*e[2]/h+l),z:Math.round(a*f[0]/i+b*f[1]/i+c*f[2]/i+m)},o={};return o[this.data.order[0]]=n.x,o[this.data.order[1]]=n.y,o[this.data.order[2]]=n.z,{x:o.xspace,y:o.yspace,z:o.zspace}}},f={slice:function(a,b,c){var e,f=this.cached_slices,g=this[this.order[0]];if(c=c||0,f[a]=f[a]||[],f[a][c]=f[a][c]||[],this[a].step<0&&(b=this[a].space_length-b),void 0!==f[a][c][b])return e=f[a][c][b],e.alpha=1,e.number=b,e;if(void 0===this.order)return!1;var h=0;this.time&&(h=c*g.height*g.width*parseFloat(g.space_length));var i=this[a].width_space.step,j=this[a].height_space.step;e={};var k,l,m,n,o,p,q,r,s,t;if(this.order[0]===a)if(l=this[a].height*this[a].width,m=this[a].height,n=this[a].width,o=1,p=n,q=l,k=new Uint16Array(l),i>0)if(j>0)for(r=0;l>r;r++)k[r]=this.data[h+q*b+r];else for(r=m;r>0;r--)for(s=0;n>s;s++)k[(m-r)*n+s]=this.data[h+q*b+r*n+s];else if(0>j)for(r=0;m>r;r++)for(s=0;n>s;s++)k[r*n+s]=this.data[h+q*b+r*n+n-s];else for(r=m;r>0;r--)for(s=0;n>s;s++)k[(m-r)*n+s]=this.data[h+q*b+r*n+n-s];else if(this.order[1]===a)if(m=this[a].height,l=this[a].height*this[a].width,n=this[a].width,o=1,p=g.slice_length,q=g.width,k=new Uint8Array(l),0>j)for(s=0;m>s;s++)for(t=0;n>t;t++)k[s*n+t]=this.data[h+b*q+p*t+s];else for(s=m;s>=0;s--)for(t=0;n>t;t++)k[(m-s)*n+t]=this.data[h+b*q+p*t+s];else for(m=this[a].height,l=this[a].height*this[a].width,n=this[a].width,o=g.slice_length,p=g.width,q=1,k=new Uint16Array(l),s=0;m>s;s++)for(t=0;n>t;t++)k[s*n+t]=this.data[h+b+g.width*s+t*g.slice_length];return e.width_space=this[a].width_space,e.height_space=this[a].height_space,e.width=n,e.height=m,"xspace"===a&&"yspace"===this.xspace.height_space.name&&(k=this.zspace.step<0?d.utils.rotateUint16Array90Right(k,e.width,e.height):d.utils.rotateUint16Array90Left(k,e.width,e.height),e.width_space=this[a].height_space,e.height_space=this[a].width_space,e.width=m,e.height=n),"yspace"===a&&"xspace"===this.yspace.height_space.name&&(k=this.zspace.step<0?d.utils.rotateUint16Array90Right(k,e.width,e.height):d.utils.rotateUint16Array90Left(k,e.width,e.height),e.width_space=this[a].height_space,e.height_space=this[a].width_space,e.width=m,e.height=n),"zspace"===a&&"xspace"===this.zspace.height_space.name&&(k=d.utils.rotateUint16Array90Left(k,e.width,e.height),e.width_space=this[a].width_space,e.height_space=this[a].height_space,e.width=m,e.height=n),e.data=k,e.width_space=e.width_space||this[a].width_space,e.height_space=e.height_space||this[a].height_space,e.width=e.width||n,e.height=e.height||m,f[a][c][b]=e,e}};d.volume_loaders.minc=function(c,d){var e;if(c.header_url&&c.raw_data_url)BrainBrowser.loader.loadFromURL(c.header_url,function(e){a(e,function(a){BrainBrowser.loader.loadFromURL(c.raw_data_url,function(c){b(a,c,d)},{result_type:"arraybuffer"})})});else{if(!c.header_file||!c.raw_data_file)throw e="invalid volume description.\nDescription must contain property pair 'header_url' and 'raw_data_url', or\n'header_file' and 'raw_data_file'.",BrainBrowser.events.triggerEvent("error",e),new Error(e);BrainBrowser.loader.loadFromFile(c.header_file,function(e){a(e,function(a){BrainBrowser.loader.loadFromFile(c.raw_data_file,function(c){b(a,c,d)},{result_type:"arraybuffer"})})})}}}(),function(){"use strict";function a(a,b){var c,d,e,f,g,h,i,j=a.length,k=b.data,l=b.width,m=b.height,n=[];if(j>1){for(c=0;m>c;c+=1)for(e=0;l>e;e+=1)for(d=0;j>d;d+=1)n[d]=n[d]||0,f=a[d],c. +*/ + +/* +* BrainBrowser v2.0.1 +* +* Author: Tarek Sherif (http://tareksherif.ca/) +* Author: Nicolas Kassis +*/ +!function(){"use strict";function a(a,c,d,e,f){a=a||[],c=c||[],d=d||[],e=e||[.7,.7,.7,1];var g,h,i,j,k,l,m,n,o,p,q,r,s,t,u=a.length,v=3*u,w=4*u,x=d.length>0,y={},z={};4===e.length&&(m=!0,i=e[0],j=e[1],k=e[2],l=e[3]);var A=new Float32Array(v),B=x?new Float32Array(v):new Float32Array,C=new Float32Array(w);for(f&&(g=new Float32Array(2*v),h=new Float32Array(2*w)),n=0,o=a.length;o>n;n++)b(y,c[3*a[n]],c[3*a[n]+1],c[3*a[n]+2]);for(z.x=y.minX+(y.maxX-y.minX)/2,z.y=y.minY+(y.maxY-y.minY)/2,z.z=y.minZ+(y.maxZ-y.minZ)/2,z.bounding_box=y,n=0,o=u;o>n;n+=3)q=3*n,r=4*n,A[q]=c[3*a[n]]-z.x,A[q+1]=c[3*a[n]+1]-z.y,A[q+2]=c[3*a[n]+2]-z.z,A[q+3]=c[3*a[n+1]]-z.x,A[q+4]=c[3*a[n+1]+1]-z.y,A[q+5]=c[3*a[n+1]+2]-z.z,A[q+6]=c[3*a[n+2]]-z.x,A[q+7]=c[3*a[n+2]+1]-z.y,A[q+8]=c[3*a[n+2]+2]-z.z,x&&(B[q]=d[3*a[n]],B[q+1]=d[3*a[n]+1],B[q+2]=d[3*a[n]+2],B[q+3]=d[3*a[n+1]],B[q+4]=d[3*a[n+1]+1],B[q+5]=d[3*a[n+1]+2],B[q+6]=d[3*a[n+2]],B[q+7]=d[3*a[n+2]+1],B[q+8]=d[3*a[n+2]+2]),m?(C[r]=i,C[r+1]=j,C[r+2]=k,C[r+3]=l,C[r+4]=i,C[r+5]=j,C[r+6]=k,C[r+7]=l,C[r+8]=i,C[r+9]=j,C[r+10]=k,C[r+11]=l):(C[r]=e[4*a[n]],C[r+1]=e[4*a[n]+1],C[r+2]=e[4*a[n]+2],C[r+3]=e[4*a[n]+3],C[r+4]=e[4*a[n+1]],C[r+5]=e[4*a[n+1]+1],C[r+6]=e[4*a[n+1]+2],C[r+7]=e[4*a[n+1]+3],C[r+8]=e[4*a[n+2]],C[r+9]=e[4*a[n+2]+1],C[r+10]=e[4*a[n+2]+2],C[r+11]=e[4*a[n+2]+3]),f&&(p=2*q,s=2*r,g[p]=A[q],g[p+1]=A[q+1],g[p+2]=A[q+2],g[p+3]=A[q+3],g[p+4]=A[q+4],g[p+5]=A[q+5],g[p+6]=A[q+3],g[p+7]=A[q+4],g[p+8]=A[q+5],g[p+9]=A[q+6],g[p+10]=A[q+7],g[p+11]=A[q+8],g[p+12]=A[q+6],g[p+13]=A[q+7],g[p+14]=A[q+8],g[p+15]=A[q],g[p+16]=A[q+1],g[p+17]=A[q+2],h[s]=C[r],h[s+1]=C[r+1],h[s+2]=C[r+2],h[s+3]=C[r+3],h[s+4]=C[r+4],h[s+5]=C[r+5],h[s+6]=C[r+6],h[s+7]=C[r+7],h[s+8]=C[r+4],h[s+9]=C[r+5],h[s+10]=C[r+6],h[s+11]=C[r+7],h[s+12]=C[r+8],h[s+13]=C[r+9],h[s+14]=C[r+10],h[s+15]=C[r+11],h[s+16]=C[r+8],h[s+17]=C[r+9],h[s+18]=C[r+10],h[s+19]=C[r+11],h[s+20]=C[r],h[s+21]=C[r+1],h[s+22]=C[r+2],h[s+23]=C[r+3]);return t={centroid:z,unindexed:{position:A,normal:B,color:C}},f&&(t.wireframe={position:g,color:h}),t}function b(a,b,c,d){(!a.minX||a.minX>b)&&(a.minX=b),(!a.maxX||a.maxXc)&&(a.minY=c),(!a.maxY||a.maxYd)&&(a.minZ=d),(!a.maxZ||a.maxZc;c++)e=h[c],f=a(h[c].indices,i,j,k,"line"!==g.type),e.centroid=f.centroid,e.unindexed=f.unindexed,e.wireframe=f.wireframe;self.postMessage(g)})}(); \ No newline at end of file diff --git a/build/brainbrowser-2.0.1/workers/freesurferasc.intensity.worker.js b/build/brainbrowser-2.0.1/workers/freesurferasc.intensity.worker.js new file mode 100644 index 00000000..8e3ced99 --- /dev/null +++ b/build/brainbrowser-2.0.1/workers/freesurferasc.intensity.worker.js @@ -0,0 +1,29 @@ +/* +* BrainBrowser: Web-based Neurological Visualization Tools +* (https://brainbrowser.cbrain.mcgill.ca) +* +* Copyright (C) 2011 +* The Royal Institution for the Advancement of Learning +* McGill University +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +*/ + +/* +* BrainBrowser v2.0.1 +* +* Author: Tarek Sherif (http://tareksherif.ca/) +* Author: Nicolas Kassis +*/ +!function(){"use strict";function a(a){var b,c,d,e,f,g,h={values:[]};for(a=a.replace(/^\s+/,"").replace(/\s+$/,""),b=a.split("\n"),c=parseFloat(b[0].replace(/^\s+/,"").replace(/\s+$/,"").split(/\s+/)[4]),h.values[0]=c,f=c,g=c,d=1,e=b.length;e>d;d++)c=parseFloat(b[d].replace(/^\s+/,"").replace(/\s+$/,"").split(/\s+/)[4]),h.values[d]=c,f=Math.min(f,c),g=Math.max(g,c);return h.min=f,h.max=g,h}self.addEventListener("message",function(b){var c=b.data,d=c.data;self.postMessage(a(d))})}(); \ No newline at end of file diff --git a/build/brainbrowser-2.0.1/workers/freesurferasc.worker.js b/build/brainbrowser-2.0.1/workers/freesurferasc.worker.js new file mode 100644 index 00000000..69fc19f1 --- /dev/null +++ b/build/brainbrowser-2.0.1/workers/freesurferasc.worker.js @@ -0,0 +1,29 @@ +/* +* BrainBrowser: Web-based Neurological Visualization Tools +* (https://brainbrowser.cbrain.mcgill.ca) +* +* Copyright (C) 2011 +* The Royal Institution for the Advancement of Learning +* McGill University +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +*/ + +/* +* BrainBrowser v2.0.1 +* +* Author: Tarek Sherif (http://tareksherif.ca/) +* Author: Nicolas Kassis +*/ +!function(){"use strict";function a(a){var b,c,d,e,f,g,h,i=[],j={};for(a=a.split("\n"),j.shapes=[],b={name:"undefined"|a.name,faces:[],indices:[]},j.shapes.push(b),c=a[1].replace(/^\s+/,"").replace(/\s+$/,"").split(/\s+/),d=parseInt(c[0],10),e=parseInt(c[1],10),h=2;d+2>h;h++)f=a[h].replace(/^\s+/,"").replace(/\s+$/,"").split(/\s+/),i.push(parseFloat(f[0])),i.push(parseFloat(f[1])),i.push(parseFloat(f[2]));for(h=d+2;d+e+2>h;h++)f=a[h].replace(/^\s+/,"").replace(/\s+$/,"").split(/\s+/),g=[],g.push(parseInt(f[0],10)),g.push(parseInt(f[1],10)),g.push(parseInt(f[2],10)),Array.prototype.push.apply(b.indices,g),b.faces.push(g);return j.type="polygon",j.vertices=i,j.colors=[.8,.8,.8,1],j}self.addEventListener("message",function(b){self.postMessage(a(b.data.data))})}(); \ No newline at end of file diff --git a/build/brainbrowser-2.0.1/workers/json.worker.js b/build/brainbrowser-2.0.1/workers/json.worker.js new file mode 100644 index 00000000..951fcdd3 --- /dev/null +++ b/build/brainbrowser-2.0.1/workers/json.worker.js @@ -0,0 +1,29 @@ +/* +* BrainBrowser: Web-based Neurological Visualization Tools +* (https://brainbrowser.cbrain.mcgill.ca) +* +* Copyright (C) 2011 +* The Royal Institution for the Advancement of Learning +* McGill University +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +*/ + +/* +* BrainBrowser v2.0.1 +* +* Author: Tarek Sherif (http://tareksherif.ca/) +* Author: Nicolas Kassis +*/ +!function(){"use strict";function a(a){var e={name:a.name,type:a.type,shapes:[]};return e.vertices=b(a.vertices),a.colors&&(e.colors=b(a.colors),(e.vertices.length===e.colors.length||3===e.colors.length)&&(e.colors=c(e.colors))),a.normals&&(e.normals=b(a.normals)),void 0===a.shapes&&(a.shapes=[]),a.indices&&a.shapes.push({indices:a.indices}),a.shapes.forEach(function(a){var c=b(a.indices);a.one_indexed&&d(c),e.shapes.push({name:a.name,indices:c})}),e}function b(a,c){if(!Array.isArray(a))return[a];if(c=c||0,c===a.length)return[];var d,e,f=[];for(d=0,e=a.length;e>d;d++)f.push.apply(f,b(a[d]));return f}function c(a){var b,c,d,e;for(b=new Float32Array(4*a.length/3),c=d=0,e=a.length;e>c;)b[d++]=a[c++],b[d++]=a[c++],b[d++]=a[c++],b[d++]=1;return b}function d(a){var b,c;for(b=0,c=a.length;c>b;b++)a[b]=a[b]-1}self.addEventListener("message",function(b){self.postMessage(a(JSON.parse(b.data.data)))})}(); \ No newline at end of file diff --git a/build/brainbrowser-2.0.1/workers/mniobj.intensity.worker.js b/build/brainbrowser-2.0.1/workers/mniobj.intensity.worker.js new file mode 100644 index 00000000..69e92cdd --- /dev/null +++ b/build/brainbrowser-2.0.1/workers/mniobj.intensity.worker.js @@ -0,0 +1,29 @@ +/* +* BrainBrowser: Web-based Neurological Visualization Tools +* (https://brainbrowser.cbrain.mcgill.ca) +* +* Copyright (C) 2011 +* The Royal Institution for the Advancement of Learning +* McGill University +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +*/ + +/* +* BrainBrowser v2.0.1 +* +* Author: Tarek Sherif (http://tareksherif.ca/) +* Author: Nicolas Kassis +*/ +!function(){"use strict";function a(a){var b,c,d,e,f={};for(f.values=a.replace(/^\s+/,"").replace(/\s+$/,"").split(/\s+/).map(parseFloat),d=f.values[0],e=f.values[0],b=1,c=f.values.length;c>b;b++)d=Math.min(d,f.values[b]),e=Math.max(e,f.values[b]);return f.min=d,f.max=e,f}self.addEventListener("message",function(b){var c=b.data,d=c.data;self.postMessage(a(d))})}(); \ No newline at end of file diff --git a/build/brainbrowser-2.0.1/workers/mniobj.worker.js b/build/brainbrowser-2.0.1/workers/mniobj.worker.js new file mode 100644 index 00000000..139aad5b --- /dev/null +++ b/build/brainbrowser-2.0.1/workers/mniobj.worker.js @@ -0,0 +1,29 @@ +/* +* BrainBrowser: Web-based Neurological Visualization Tools +* (https://brainbrowser.cbrain.mcgill.ca) +* +* Copyright (C) 2011 +* The Royal Institution for the Advancement of Learning +* McGill University +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +*/ + +/* +* BrainBrowser v2.0.1 +* +* Author: Tarek Sherif (http://tareksherif.ca/) +* Author: Nicolas Kassis +*/ +!function(){"use strict";function a(a,i){var j,k,l,m,n,o,p,q=a.replace(/\s+$/,"").replace(/^\s+/,""),r=[],s=i.split,t={},u=q.split(/\s+/).reverse(),v=u.pop();if(t.split=!1,t.type="P"===v?"polygon":"L"===v?"line":v,"polygon"===t.type)b(t,u),t.num_vertices=parseInt(u.pop(),10),c(t,u),d(t,u),t.nitems=parseInt(u.pop(),10);else{if("line"!==t.type)return t.error=!0,void(t.error_message='Invalid MNI Object class: must be "polygon" or "line"');b(t,u),t.num_vertices=parseInt(u.pop(),10),c(t,u),t.nitems=parseInt(u.pop(),10)}if(e(t,u),f(t,u),g(t,u),"polygon"===t.type)s&&(t.split=!0,h(t,u));else if("line"===t.type){for(o=t.indices,p=t.end_indices,n=t.nitems,j=0;n>j;j++){for(l=0===j?0:p[j-1],r.push(o[l]),m=p[j],k=l+1;m-1>k;k++)r.push(o[k]),r.push(o[k]);r.push(o[m-1])}t.indices=r}return t}function b(a,b){"polygon"===a.type?a.surface_properties={ambient:parseFloat(b.pop()),diffuse:parseFloat(b.pop()),specular_reflectance:parseFloat(b.pop()),specular_scattering:parseFloat(b.pop()),transparency:parseFloat(b.pop())}:"line"===a.type&&(a.surfaceProperties={width:b.pop()})}function c(a,b){var c,d,e=[],f=a.num_vertices;for(c=0;f>c;c++)for(d=0;3>d;d++)e.push(parseFloat(b.pop()));a.vertices=e}function d(a,b){var c,d,e=[],f=a.num_vertices;for(c=0;f>c;c++)for(d=0;3>d;d++)e.push(parseFloat(b.pop()));a.normals=e}function e(a,b){var c,d,e,f=[],g=parseInt(b.pop(),10);if(0===g)for(c=0;4>c;c++)f.push(parseFloat(b.pop()));else if(1===g)for(d=0,e=a.num_polygons;e>d;d++)for(c=0;4>c;c++)f.push(parseFloat(b.pop()));else{if(2!==g)throw new Error("color_flag not valid in that file");for(d=0,e=a.num_vertices;e>d;d++)for(c=0;4>c;c++)f.push(parseFloat(b.pop()))}a.color_flag=g,a.colors=f}function f(a,b){var c,d,e=[];for(c=0,d=a.nitems;d>c;c++)e.push(parseInt(b.pop(),10));a.end_indices=e}function g(a,b){var c,d,e,f=b.length,g=[];for(d=0,e=b.length;f>d;d++)c=parseInt(b.pop(),10),g.push(c);a.indices=g}function h(a){var b=a.indices.length;a.left={indices:a.indices.slice(0,b/2)},a.right={indices:a.indices.slice(b/2)}}self.addEventListener("message",function(b){var c=b.data,d=a(c.data,c.options)||{error:!0,error_message:"Error parsing data."},e={type:d.type,vertices:d.vertices,normals:d.normals,colors:d.colors,surface_properties:d.surface_properties,split:d.split,error:d.error,error_message:d.error_message};e.shapes=e.split?[{indices:d.left.indices},{indices:d.right.indices}]:[{indices:d.indices}],self.postMessage(e)})}(); \ No newline at end of file diff --git a/build/brainbrowser-2.0.1/workers/wavefrontobj.worker.js b/build/brainbrowser-2.0.1/workers/wavefrontobj.worker.js new file mode 100644 index 00000000..abf6a7f8 --- /dev/null +++ b/build/brainbrowser-2.0.1/workers/wavefrontobj.worker.js @@ -0,0 +1,29 @@ +/* +* BrainBrowser: Web-based Neurological Visualization Tools +* (https://brainbrowser.cbrain.mcgill.ca) +* +* Copyright (C) 2011 +* The Royal Institution for the Advancement of Learning +* McGill University +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +*/ + +/* +* BrainBrowser v2.0.1 +* +* Author: Tarek Sherif (http://tareksherif.ca/) +* Author: Nicolas Kassis +*/ +!function(){"use strict";function a(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o=[],p=[],q=[],r={};for(a=a.split("\n"),r.shapes=[],b={name:"undefined"|a.name,faces:[],indices:[],texture_indices:[],normal_indices:[]},r.shapes.push(b),i=0,l=a.length;l>i;i++)if(f=a[i].replace(/^\s+/,"").replace(/\s+$/,"").split(/\s+/),g=f[0],h=f.length,!g.match("#")||""===f)switch(g){case"o":case"g":b={name:f[1],faces:[],indices:[],texture_indices:[],normal_indices:[]},r.shapes.push(b);break;case"v":o.push(parseFloat(f[1])),o.push(parseFloat(f[2])),o.push(parseFloat(f[3]));break;case"vt":for(j=1;h>j;j++)p.push(parseFloat(f[j]));break;case"vn":q.push(parseFloat(f[1])),q.push(parseFloat(f[2])),q.push(parseFloat(f[3]));break;case"f":m=[],c=b.indices,d=b.texture_indices,e=b.normal_indices;var s=f[1].split("/");for(k=2;h-1>k;k++)m.push(parseInt(s[0],10)-1),c.push(parseInt(s[0],10)-1),d.push(parseInt(s[1],10)-1),s[2]&&e.push(parseInt(s[2],10)-1),n=f[k].split("/"),m.push(parseInt(n[0],10)-1),c.push(parseInt(n[0],10)-1),d.push(parseInt(n[1],10)-1),n[2]&&e.push(parseInt(n[2],10)-1),n=f[k+1].split("/"),m.push(parseInt(n[0],10)-1),c.push(parseInt(n[0],10)-1),d.push(parseInt(n[1],10)-1),n[2]&&e.push(parseInt(n[2],10)-1);b.faces.push(m)}return r.type="polygon",r.vertices=o,r.normals=q,r.colors=[.8,.8,.8,1],r.texture_coords=p,r}self.addEventListener("message",function(b){self.postMessage(a(b.data.data))})}(); \ No newline at end of file diff --git a/package.json b/package.json index 7cd84a47..c6ae59d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "brainbrowser", - "version": "2.0.0", + "version": "2.0.1", "license": "GNU Affero GPL 3.0", "devDependencies": { "grunt": "~0.4.1", diff --git a/release/brainbrowser-2.0.1.tar.gz b/release/brainbrowser-2.0.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..369276516442ef2aae7be740fe8f1ffbeeb3ec05 GIT binary patch literal 22296 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 literal 0 HcmV?d00001