@niivue/niivue 0.43.2 → 0.43.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- (function(Nt,at){typeof exports=="object"&&typeof module<"u"?at(exports):typeof define=="function"&&define.amd?define(["exports"],at):(Nt=typeof globalThis<"u"?globalThis:Nt||self,at(Nt.niivue={}))})(this,function(exports){"use strict";var zp=Object.defineProperty;var Qp=(Nt,at,qt)=>at in Nt?zp(Nt,at,{enumerable:!0,configurable:!0,writable:!0,value:qt}):Nt[at]=qt;var g0=(Nt,at,qt)=>(Qp(Nt,typeof at!="symbol"?at+"":at,qt),qt);function _mergeNamespaces(T,u){for(var h=0;h<u.length;h++){const g=u[h];if(typeof g!="string"&&!Array.isArray(g)){for(const v in g)if(v!=="default"&&!(v in T)){const w=Object.getOwnPropertyDescriptor(g,v);w&&Object.defineProperty(T,v,w.get?w:{enumerable:!0,get:()=>g[v]})}}}return Object.freeze(Object.defineProperty(T,Symbol.toStringTag,{value:"Module"}))}var EPSILON=1e-6,ARRAY_TYPE=typeof Float32Array<"u"?Float32Array:Array;Math.hypot||(Math.hypot=function(){for(var T=0,u=arguments.length;u--;)T+=arguments[u]*arguments[u];return Math.sqrt(T)});function create$4(){var T=new ARRAY_TYPE(9);return ARRAY_TYPE!=Float32Array&&(T[1]=0,T[2]=0,T[3]=0,T[5]=0,T[6]=0,T[7]=0),T[0]=1,T[4]=1,T[8]=1,T}function fromValues$4(T,u,h,g,v,w,C,k,U){var N=new ARRAY_TYPE(9);return N[0]=T,N[1]=u,N[2]=h,N[3]=g,N[4]=v,N[5]=w,N[6]=C,N[7]=k,N[8]=U,N}function multiply$1(T,u,h){var g=u[0],v=u[1],w=u[2],C=u[3],k=u[4],U=u[5],N=u[6],O=u[7],d=u[8],M=h[0],e=h[1],b=h[2],z=h[3],W=h[4],s0=h[5],K=h[6],J=h[7],D=h[8];return T[0]=M*g+e*C+b*N,T[1]=M*v+e*k+b*O,T[2]=M*w+e*U+b*d,T[3]=z*g+W*C+s0*N,T[4]=z*v+W*k+s0*O,T[5]=z*w+W*U+s0*d,T[6]=K*g+J*C+D*N,T[7]=K*v+J*k+D*O,T[8]=K*w+J*U+D*d,T}function create$3(){var T=new ARRAY_TYPE(16);return ARRAY_TYPE!=Float32Array&&(T[1]=0,T[2]=0,T[3]=0,T[4]=0,T[6]=0,T[7]=0,T[8]=0,T[9]=0,T[11]=0,T[12]=0,T[13]=0,T[14]=0),T[0]=1,T[5]=1,T[10]=1,T[15]=1,T}function clone$2(T){var u=new ARRAY_TYPE(16);return u[0]=T[0],u[1]=T[1],u[2]=T[2],u[3]=T[3],u[4]=T[4],u[5]=T[5],u[6]=T[6],u[7]=T[7],u[8]=T[8],u[9]=T[9],u[10]=T[10],u[11]=T[11],u[12]=T[12],u[13]=T[13],u[14]=T[14],u[15]=T[15],u}function copy$1(T,u){return T[0]=u[0],T[1]=u[1],T[2]=u[2],T[3]=u[3],T[4]=u[4],T[5]=u[5],T[6]=u[6],T[7]=u[7],T[8]=u[8],T[9]=u[9],T[10]=u[10],T[11]=u[11],T[12]=u[12],T[13]=u[13],T[14]=u[14],T[15]=u[15],T}function fromValues$3(T,u,h,g,v,w,C,k,U,N,O,d,M,e,b,z){var W=new ARRAY_TYPE(16);return W[0]=T,W[1]=u,W[2]=h,W[3]=g,W[4]=v,W[5]=w,W[6]=C,W[7]=k,W[8]=U,W[9]=N,W[10]=O,W[11]=d,W[12]=M,W[13]=e,W[14]=b,W[15]=z,W}function identity$1(T){return T[0]=1,T[1]=0,T[2]=0,T[3]=0,T[4]=0,T[5]=1,T[6]=0,T[7]=0,T[8]=0,T[9]=0,T[10]=1,T[11]=0,T[12]=0,T[13]=0,T[14]=0,T[15]=1,T}function transpose(T,u){if(T===u){var h=u[1],g=u[2],v=u[3],w=u[6],C=u[7],k=u[11];T[1]=u[4],T[2]=u[8],T[3]=u[12],T[4]=h,T[6]=u[9],T[7]=u[13],T[8]=g,T[9]=w,T[11]=u[14],T[12]=v,T[13]=C,T[14]=k}else T[0]=u[0],T[1]=u[4],T[2]=u[8],T[3]=u[12],T[4]=u[1],T[5]=u[5],T[6]=u[9],T[7]=u[13],T[8]=u[2],T[9]=u[6],T[10]=u[10],T[11]=u[14],T[12]=u[3],T[13]=u[7],T[14]=u[11],T[15]=u[15];return T}function invert(T,u){var h=u[0],g=u[1],v=u[2],w=u[3],C=u[4],k=u[5],U=u[6],N=u[7],O=u[8],d=u[9],M=u[10],e=u[11],b=u[12],z=u[13],W=u[14],s0=u[15],K=h*k-g*C,J=h*U-v*C,D=h*N-w*C,Z=g*U-v*k,X=g*N-w*k,r0=v*N-w*U,l0=O*z-d*b,j=O*W-M*b,f=O*s0-e*b,c0=d*W-M*z,h0=d*s0-e*z,A0=M*s0-e*W,w0=K*A0-J*h0+D*c0+Z*f-X*j+r0*l0;return w0?(w0=1/w0,T[0]=(k*A0-U*h0+N*c0)*w0,T[1]=(v*h0-g*A0-w*c0)*w0,T[2]=(z*r0-W*X+s0*Z)*w0,T[3]=(M*X-d*r0-e*Z)*w0,T[4]=(U*f-C*A0-N*j)*w0,T[5]=(h*A0-v*f+w*j)*w0,T[6]=(W*D-b*r0-s0*J)*w0,T[7]=(O*r0-M*D+e*J)*w0,T[8]=(C*h0-k*f+N*l0)*w0,T[9]=(g*f-h*h0-w*l0)*w0,T[10]=(b*X-z*D+s0*K)*w0,T[11]=(d*D-O*X-e*K)*w0,T[12]=(k*j-C*c0-U*l0)*w0,T[13]=(h*c0-g*j+v*l0)*w0,T[14]=(z*J-b*Z-W*K)*w0,T[15]=(O*Z-d*J+M*K)*w0,T):null}function multiply(T,u,h){var g=u[0],v=u[1],w=u[2],C=u[3],k=u[4],U=u[5],N=u[6],O=u[7],d=u[8],M=u[9],e=u[10],b=u[11],z=u[12],W=u[13],s0=u[14],K=u[15],J=h[0],D=h[1],Z=h[2],X=h[3];return T[0]=J*g+D*k+Z*d+X*z,T[1]=J*v+D*U+Z*M+X*W,T[2]=J*w+D*N+Z*e+X*s0,T[3]=J*C+D*O+Z*b+X*K,J=h[4],D=h[5],Z=h[6],X=h[7],T[4]=J*g+D*k+Z*d+X*z,T[5]=J*v+D*U+Z*M+X*W,T[6]=J*w+D*N+Z*e+X*s0,T[7]=J*C+D*O+Z*b+X*K,J=h[8],D=h[9],Z=h[10],X=h[11],T[8]=J*g+D*k+Z*d+X*z,T[9]=J*v+D*U+Z*M+X*W,T[10]=J*w+D*N+Z*e+X*s0,T[11]=J*C+D*O+Z*b+X*K,J=h[12],D=h[13],Z=h[14],X=h[15],T[12]=J*g+D*k+Z*d+X*z,T[13]=J*v+D*U+Z*M+X*W,T[14]=J*w+D*N+Z*e+X*s0,T[15]=J*C+D*O+Z*b+X*K,T}function translate(T,u,h){var g=h[0],v=h[1],w=h[2],C,k,U,N,O,d,M,e,b,z,W,s0;return u===T?(T[12]=u[0]*g+u[4]*v+u[8]*w+u[12],T[13]=u[1]*g+u[5]*v+u[9]*w+u[13],T[14]=u[2]*g+u[6]*v+u[10]*w+u[14],T[15]=u[3]*g+u[7]*v+u[11]*w+u[15]):(C=u[0],k=u[1],U=u[2],N=u[3],O=u[4],d=u[5],M=u[6],e=u[7],b=u[8],z=u[9],W=u[10],s0=u[11],T[0]=C,T[1]=k,T[2]=U,T[3]=N,T[4]=O,T[5]=d,T[6]=M,T[7]=e,T[8]=b,T[9]=z,T[10]=W,T[11]=s0,T[12]=C*g+O*v+b*w+u[12],T[13]=k*g+d*v+z*w+u[13],T[14]=U*g+M*v+W*w+u[14],T[15]=N*g+e*v+s0*w+u[15]),T}function scale$3(T,u,h){var g=h[0],v=h[1],w=h[2];return T[0]=u[0]*g,T[1]=u[1]*g,T[2]=u[2]*g,T[3]=u[3]*g,T[4]=u[4]*v,T[5]=u[5]*v,T[6]=u[6]*v,T[7]=u[7]*v,T[8]=u[8]*w,T[9]=u[9]*w,T[10]=u[10]*w,T[11]=u[11]*w,T[12]=u[12],T[13]=u[13],T[14]=u[14],T[15]=u[15],T}function rotateX(T,u,h){var g=Math.sin(h),v=Math.cos(h),w=u[4],C=u[5],k=u[6],U=u[7],N=u[8],O=u[9],d=u[10],M=u[11];return u!==T&&(T[0]=u[0],T[1]=u[1],T[2]=u[2],T[3]=u[3],T[12]=u[12],T[13]=u[13],T[14]=u[14],T[15]=u[15]),T[4]=w*v+N*g,T[5]=C*v+O*g,T[6]=k*v+d*g,T[7]=U*v+M*g,T[8]=N*v-w*g,T[9]=O*v-C*g,T[10]=d*v-k*g,T[11]=M*v-U*g,T}function rotateZ(T,u,h){var g=Math.sin(h),v=Math.cos(h),w=u[0],C=u[1],k=u[2],U=u[3],N=u[4],O=u[5],d=u[6],M=u[7];return u!==T&&(T[8]=u[8],T[9]=u[9],T[10]=u[10],T[11]=u[11],T[12]=u[12],T[13]=u[13],T[14]=u[14],T[15]=u[15]),T[0]=w*v+N*g,T[1]=C*v+O*g,T[2]=k*v+d*g,T[3]=U*v+M*g,T[4]=N*v-w*g,T[5]=O*v-C*g,T[6]=d*v-k*g,T[7]=M*v-U*g,T}function fromRotation(T,u,h){var g=h[0],v=h[1],w=h[2],C=Math.hypot(g,v,w),k,U,N;return C<EPSILON?null:(C=1/C,g*=C,v*=C,w*=C,k=Math.sin(u),U=Math.cos(u),N=1-U,T[0]=g*g*N+U,T[1]=v*g*N+w*k,T[2]=w*g*N-v*k,T[3]=0,T[4]=g*v*N-w*k,T[5]=v*v*N+U,T[6]=w*v*N+g*k,T[7]=0,T[8]=g*w*N+v*k,T[9]=v*w*N-g*k,T[10]=w*w*N+U,T[11]=0,T[12]=0,T[13]=0,T[14]=0,T[15]=1,T)}function orthoNO(T,u,h,g,v,w,C){var k=1/(u-h),U=1/(g-v),N=1/(w-C);return T[0]=-2*k,T[1]=0,T[2]=0,T[3]=0,T[4]=0,T[5]=-2*U,T[6]=0,T[7]=0,T[8]=0,T[9]=0,T[10]=2*N,T[11]=0,T[12]=(u+h)*k,T[13]=(v+g)*U,T[14]=(C+w)*N,T[15]=1,T}var ortho=orthoNO;function multiplyScalar(T,u,h){return T[0]=u[0]*h,T[1]=u[1]*h,T[2]=u[2]*h,T[3]=u[3]*h,T[4]=u[4]*h,T[5]=u[5]*h,T[6]=u[6]*h,T[7]=u[7]*h,T[8]=u[8]*h,T[9]=u[9]*h,T[10]=u[10]*h,T[11]=u[11]*h,T[12]=u[12]*h,T[13]=u[13]*h,T[14]=u[14]*h,T[15]=u[15]*h,T}var mul=multiply;function create$2(){var T=new ARRAY_TYPE(3);return ARRAY_TYPE!=Float32Array&&(T[0]=0,T[1]=0,T[2]=0),T}function clone$1(T){var u=new ARRAY_TYPE(3);return u[0]=T[0],u[1]=T[1],u[2]=T[2],u}function length$1(T){var u=T[0],h=T[1],g=T[2];return Math.hypot(u,h,g)}function fromValues$2(T,u,h){var g=new ARRAY_TYPE(3);return g[0]=T,g[1]=u,g[2]=h,g}function copy(T,u){return T[0]=u[0],T[1]=u[1],T[2]=u[2],T}function add$1(T,u,h){return T[0]=u[0]+h[0],T[1]=u[1]+h[1],T[2]=u[2]+h[2],T}function subtract$1(T,u,h){return T[0]=u[0]-h[0],T[1]=u[1]-h[1],T[2]=u[2]-h[2],T}function min$j(T,u,h){return T[0]=Math.min(u[0],h[0]),T[1]=Math.min(u[1],h[1]),T[2]=Math.min(u[2],h[2]),T}function max$l(T,u,h){return T[0]=Math.max(u[0],h[0]),T[1]=Math.max(u[1],h[1]),T[2]=Math.max(u[2],h[2]),T}function scale$2(T,u,h){return T[0]=u[0]*h,T[1]=u[1]*h,T[2]=u[2]*h,T}function negate(T,u){return T[0]=-u[0],T[1]=-u[1],T[2]=-u[2],T}function normalize$1(T,u){var h=u[0],g=u[1],v=u[2],w=h*h+g*g+v*v;return w>0&&(w=1/Math.sqrt(w)),T[0]=u[0]*w,T[1]=u[1]*w,T[2]=u[2]*w,T}function dot(T,u){return T[0]*u[0]+T[1]*u[1]+T[2]*u[2]}function cross(T,u,h){var g=u[0],v=u[1],w=u[2],C=h[0],k=h[1],U=h[2];return T[0]=v*U-w*k,T[1]=w*C-g*U,T[2]=g*k-v*C,T}function lerp(T,u,h,g){var v=u[0],w=u[1],C=u[2];return T[0]=v+g*(h[0]-v),T[1]=w+g*(h[1]-w),T[2]=C+g*(h[2]-C),T}function angle(T,u){var h=T[0],g=T[1],v=T[2],w=u[0],C=u[1],k=u[2],U=Math.sqrt(h*h+g*g+v*v),N=Math.sqrt(w*w+C*C+k*k),O=U*N,d=O&&dot(T,u)/O;return Math.acos(Math.min(Math.max(d,-1),1))}var sub$1=subtract$1,len=length$1;(function(){var T=create$2();return function(u,h,g,v,w,C){var k,U;for(h||(h=3),g||(g=0),v?U=Math.min(v*h+g,u.length):U=u.length,k=g;k<U;k+=h)T[0]=u[k],T[1]=u[k+1],T[2]=u[k+2],w(T,T,C),u[k]=T[0],u[k+1]=T[1],u[k+2]=T[2];return u}})();function create$1(){var T=new ARRAY_TYPE(4);return ARRAY_TYPE!=Float32Array&&(T[0]=0,T[1]=0,T[2]=0,T[3]=0),T}function clone(T){var u=new ARRAY_TYPE(4);return u[0]=T[0],u[1]=T[1],u[2]=T[2],u[3]=T[3],u}function fromValues$1(T,u,h,g){var v=new ARRAY_TYPE(4);return v[0]=T,v[1]=u,v[2]=h,v[3]=g,v}function add(T,u,h){return T[0]=u[0]+h[0],T[1]=u[1]+h[1],T[2]=u[2]+h[2],T[3]=u[3]+h[3],T}function subtract(T,u,h){return T[0]=u[0]-h[0],T[1]=u[1]-h[1],T[2]=u[2]-h[2],T[3]=u[3]-h[3],T}function scale$1(T,u,h){return T[0]=u[0]*h,T[1]=u[1]*h,T[2]=u[2]*h,T[3]=u[3]*h,T}function transformMat4(T,u,h){var g=u[0],v=u[1],w=u[2],C=u[3];return T[0]=h[0]*g+h[4]*v+h[8]*w+h[12]*C,T[1]=h[1]*g+h[5]*v+h[9]*w+h[13]*C,T[2]=h[2]*g+h[6]*v+h[10]*w+h[14]*C,T[3]=h[3]*g+h[7]*v+h[11]*w+h[15]*C,T}var sub=subtract;(function(){var T=create$1();return function(u,h,g,v,w,C){var k,U;for(h||(h=4),g||(g=0),v?U=Math.min(v*h+g,u.length):U=u.length,k=g;k<U;k+=h)T[0]=u[k],T[1]=u[k+1],T[2]=u[k+2],T[3]=u[k+3],w(T,T,C),u[k]=T[0],u[k+1]=T[1],u[k+2]=T[2],u[k+3]=T[3];return u}})();function create(){var T=new ARRAY_TYPE(2);return ARRAY_TYPE!=Float32Array&&(T[0]=0,T[1]=0),T}function fromValues(T,u){var h=new ARRAY_TYPE(2);return h[0]=T,h[1]=u,h}function scale(T,u,h){return T[0]=u[0]*h,T[1]=u[1]*h,T}function length(T){var u=T[0],h=T[1];return Math.hypot(u,h)}function normalize(T,u){var h=u[0],g=u[1],v=h*h+g*g;return v>0&&(v=1/Math.sqrt(v)),T[0]=u[0]*v,T[1]=u[1]*v,T}(function(){var T=create();return function(u,h,g,v,w,C){var k,U;for(h||(h=2),g||(g=0),v?U=Math.min(v*h+g,u.length):U=u.length,k=g;k<U;k+=h)T[0]=u[k],T[1]=u[k+1],w(T,T,C),u[k]=T[0],u[k+1]=T[1];return u}})();const version="0.43.2",Nt=class Nt{constructor({name:u="niivue",level:h="info"}={}){g0(this,"level");g0(this,"name");this.name=`${u}`,this.level=h}debug(...u){Nt.levels[this.level]>Nt.levels.debug||console.debug(`${this.name}-debug`,...u)}info(...u){Nt.levels[this.level]>Nt.levels.info||console.info(`${this.name}-info`,...u)}warn(...u){Nt.levels[this.level]>Nt.levels.warn||console.warn(`${this.name}-warn`,...u)}error(...u){Nt.levels[this.level]>Nt.levels.error||console.error(`${this.name}-error`,...u)}fatal(...u){Nt.levels[this.level]>Nt.levels.fatal||console.error(`${this.name}-fatal`,...u)}setLogLevel(u){this.level=u}setName(u){this.name=u}};g0(Nt,"levels",{debug:0,info:1,warn:2,error:3,fatal:4,silent:1/0});let Log=Nt;const log=new Log({name:"niivue",level:"info"}),compileShader=function(T,u,h){const g=T.createShader(T.VERTEX_SHADER);if(g===null)throw new Error("could not create vertex shader");if(T.shaderSource(g,u),T.compileShader(g),!T.getShaderParameter(g,T.COMPILE_STATUS))throw log.error(T.getShaderInfoLog(g)),new Error("Vertex shader failed to compile, see console for log");const v=T.createShader(T.FRAGMENT_SHADER);if(v===null)throw new Error("could not create fragment shader");if(T.shaderSource(v,h),T.compileShader(v),!T.getShaderParameter(v,T.COMPILE_STATUS))throw log.error(T.getShaderInfoLog(v)),new Error("Fragment shader failed to compile, see console for log");const w=T.createProgram();if(w===null)throw new Error("could not create GL program");if(T.attachShader(w,g),T.attachShader(w,v),T.linkProgram(w),!T.getProgramParameter(w,T.LINK_STATUS))throw log.error(T.getProgramInfoLog(w)),new Error("Shader failed to link, see console for log");return w};class Shader{constructor(u,h,g){g0(this,"program");g0(this,"uniforms",{});g0(this,"isMatcap");this.program=compileShader(u,h,g);const v=/uniform[^;]+[ ](\w+);/g,w=/uniform[^;]+[ ](\w+);/,C=h.match(v),k=g.match(v);C&&C.forEach(U=>{const N=U.match(w);this.uniforms[N[1]]=-1}),k&&k.forEach(U=>{const N=U.match(w);this.uniforms[N[1]]=-1});for(const U in this.uniforms)this.uniforms[U]=u.getUniformLocation(this.program,U)}use(u){u.useProgram(this.program)}}const vertRenderShader=`#version 300 es
1
+ (function(Nt,at){typeof exports=="object"&&typeof module<"u"?at(exports):typeof define=="function"&&define.amd?define(["exports"],at):(Nt=typeof globalThis<"u"?globalThis:Nt||self,at(Nt.niivue={}))})(this,function(exports){"use strict";var zp=Object.defineProperty;var Qp=(Nt,at,qt)=>at in Nt?zp(Nt,at,{enumerable:!0,configurable:!0,writable:!0,value:qt}):Nt[at]=qt;var g0=(Nt,at,qt)=>(Qp(Nt,typeof at!="symbol"?at+"":at,qt),qt);function _mergeNamespaces(T,u){for(var h=0;h<u.length;h++){const g=u[h];if(typeof g!="string"&&!Array.isArray(g)){for(const v in g)if(v!=="default"&&!(v in T)){const w=Object.getOwnPropertyDescriptor(g,v);w&&Object.defineProperty(T,v,w.get?w:{enumerable:!0,get:()=>g[v]})}}}return Object.freeze(Object.defineProperty(T,Symbol.toStringTag,{value:"Module"}))}var EPSILON=1e-6,ARRAY_TYPE=typeof Float32Array<"u"?Float32Array:Array;Math.hypot||(Math.hypot=function(){for(var T=0,u=arguments.length;u--;)T+=arguments[u]*arguments[u];return Math.sqrt(T)});function create$4(){var T=new ARRAY_TYPE(9);return ARRAY_TYPE!=Float32Array&&(T[1]=0,T[2]=0,T[3]=0,T[5]=0,T[6]=0,T[7]=0),T[0]=1,T[4]=1,T[8]=1,T}function fromValues$4(T,u,h,g,v,w,C,k,U){var N=new ARRAY_TYPE(9);return N[0]=T,N[1]=u,N[2]=h,N[3]=g,N[4]=v,N[5]=w,N[6]=C,N[7]=k,N[8]=U,N}function multiply$1(T,u,h){var g=u[0],v=u[1],w=u[2],C=u[3],k=u[4],U=u[5],N=u[6],O=u[7],d=u[8],M=h[0],e=h[1],b=h[2],z=h[3],W=h[4],s0=h[5],K=h[6],J=h[7],D=h[8];return T[0]=M*g+e*C+b*N,T[1]=M*v+e*k+b*O,T[2]=M*w+e*U+b*d,T[3]=z*g+W*C+s0*N,T[4]=z*v+W*k+s0*O,T[5]=z*w+W*U+s0*d,T[6]=K*g+J*C+D*N,T[7]=K*v+J*k+D*O,T[8]=K*w+J*U+D*d,T}function create$3(){var T=new ARRAY_TYPE(16);return ARRAY_TYPE!=Float32Array&&(T[1]=0,T[2]=0,T[3]=0,T[4]=0,T[6]=0,T[7]=0,T[8]=0,T[9]=0,T[11]=0,T[12]=0,T[13]=0,T[14]=0),T[0]=1,T[5]=1,T[10]=1,T[15]=1,T}function clone$2(T){var u=new ARRAY_TYPE(16);return u[0]=T[0],u[1]=T[1],u[2]=T[2],u[3]=T[3],u[4]=T[4],u[5]=T[5],u[6]=T[6],u[7]=T[7],u[8]=T[8],u[9]=T[9],u[10]=T[10],u[11]=T[11],u[12]=T[12],u[13]=T[13],u[14]=T[14],u[15]=T[15],u}function copy$1(T,u){return T[0]=u[0],T[1]=u[1],T[2]=u[2],T[3]=u[3],T[4]=u[4],T[5]=u[5],T[6]=u[6],T[7]=u[7],T[8]=u[8],T[9]=u[9],T[10]=u[10],T[11]=u[11],T[12]=u[12],T[13]=u[13],T[14]=u[14],T[15]=u[15],T}function fromValues$3(T,u,h,g,v,w,C,k,U,N,O,d,M,e,b,z){var W=new ARRAY_TYPE(16);return W[0]=T,W[1]=u,W[2]=h,W[3]=g,W[4]=v,W[5]=w,W[6]=C,W[7]=k,W[8]=U,W[9]=N,W[10]=O,W[11]=d,W[12]=M,W[13]=e,W[14]=b,W[15]=z,W}function identity$1(T){return T[0]=1,T[1]=0,T[2]=0,T[3]=0,T[4]=0,T[5]=1,T[6]=0,T[7]=0,T[8]=0,T[9]=0,T[10]=1,T[11]=0,T[12]=0,T[13]=0,T[14]=0,T[15]=1,T}function transpose(T,u){if(T===u){var h=u[1],g=u[2],v=u[3],w=u[6],C=u[7],k=u[11];T[1]=u[4],T[2]=u[8],T[3]=u[12],T[4]=h,T[6]=u[9],T[7]=u[13],T[8]=g,T[9]=w,T[11]=u[14],T[12]=v,T[13]=C,T[14]=k}else T[0]=u[0],T[1]=u[4],T[2]=u[8],T[3]=u[12],T[4]=u[1],T[5]=u[5],T[6]=u[9],T[7]=u[13],T[8]=u[2],T[9]=u[6],T[10]=u[10],T[11]=u[14],T[12]=u[3],T[13]=u[7],T[14]=u[11],T[15]=u[15];return T}function invert(T,u){var h=u[0],g=u[1],v=u[2],w=u[3],C=u[4],k=u[5],U=u[6],N=u[7],O=u[8],d=u[9],M=u[10],e=u[11],b=u[12],z=u[13],W=u[14],s0=u[15],K=h*k-g*C,J=h*U-v*C,D=h*N-w*C,Z=g*U-v*k,X=g*N-w*k,r0=v*N-w*U,l0=O*z-d*b,j=O*W-M*b,f=O*s0-e*b,c0=d*W-M*z,h0=d*s0-e*z,A0=M*s0-e*W,w0=K*A0-J*h0+D*c0+Z*f-X*j+r0*l0;return w0?(w0=1/w0,T[0]=(k*A0-U*h0+N*c0)*w0,T[1]=(v*h0-g*A0-w*c0)*w0,T[2]=(z*r0-W*X+s0*Z)*w0,T[3]=(M*X-d*r0-e*Z)*w0,T[4]=(U*f-C*A0-N*j)*w0,T[5]=(h*A0-v*f+w*j)*w0,T[6]=(W*D-b*r0-s0*J)*w0,T[7]=(O*r0-M*D+e*J)*w0,T[8]=(C*h0-k*f+N*l0)*w0,T[9]=(g*f-h*h0-w*l0)*w0,T[10]=(b*X-z*D+s0*K)*w0,T[11]=(d*D-O*X-e*K)*w0,T[12]=(k*j-C*c0-U*l0)*w0,T[13]=(h*c0-g*j+v*l0)*w0,T[14]=(z*J-b*Z-W*K)*w0,T[15]=(O*Z-d*J+M*K)*w0,T):null}function multiply(T,u,h){var g=u[0],v=u[1],w=u[2],C=u[3],k=u[4],U=u[5],N=u[6],O=u[7],d=u[8],M=u[9],e=u[10],b=u[11],z=u[12],W=u[13],s0=u[14],K=u[15],J=h[0],D=h[1],Z=h[2],X=h[3];return T[0]=J*g+D*k+Z*d+X*z,T[1]=J*v+D*U+Z*M+X*W,T[2]=J*w+D*N+Z*e+X*s0,T[3]=J*C+D*O+Z*b+X*K,J=h[4],D=h[5],Z=h[6],X=h[7],T[4]=J*g+D*k+Z*d+X*z,T[5]=J*v+D*U+Z*M+X*W,T[6]=J*w+D*N+Z*e+X*s0,T[7]=J*C+D*O+Z*b+X*K,J=h[8],D=h[9],Z=h[10],X=h[11],T[8]=J*g+D*k+Z*d+X*z,T[9]=J*v+D*U+Z*M+X*W,T[10]=J*w+D*N+Z*e+X*s0,T[11]=J*C+D*O+Z*b+X*K,J=h[12],D=h[13],Z=h[14],X=h[15],T[12]=J*g+D*k+Z*d+X*z,T[13]=J*v+D*U+Z*M+X*W,T[14]=J*w+D*N+Z*e+X*s0,T[15]=J*C+D*O+Z*b+X*K,T}function translate(T,u,h){var g=h[0],v=h[1],w=h[2],C,k,U,N,O,d,M,e,b,z,W,s0;return u===T?(T[12]=u[0]*g+u[4]*v+u[8]*w+u[12],T[13]=u[1]*g+u[5]*v+u[9]*w+u[13],T[14]=u[2]*g+u[6]*v+u[10]*w+u[14],T[15]=u[3]*g+u[7]*v+u[11]*w+u[15]):(C=u[0],k=u[1],U=u[2],N=u[3],O=u[4],d=u[5],M=u[6],e=u[7],b=u[8],z=u[9],W=u[10],s0=u[11],T[0]=C,T[1]=k,T[2]=U,T[3]=N,T[4]=O,T[5]=d,T[6]=M,T[7]=e,T[8]=b,T[9]=z,T[10]=W,T[11]=s0,T[12]=C*g+O*v+b*w+u[12],T[13]=k*g+d*v+z*w+u[13],T[14]=U*g+M*v+W*w+u[14],T[15]=N*g+e*v+s0*w+u[15]),T}function scale$3(T,u,h){var g=h[0],v=h[1],w=h[2];return T[0]=u[0]*g,T[1]=u[1]*g,T[2]=u[2]*g,T[3]=u[3]*g,T[4]=u[4]*v,T[5]=u[5]*v,T[6]=u[6]*v,T[7]=u[7]*v,T[8]=u[8]*w,T[9]=u[9]*w,T[10]=u[10]*w,T[11]=u[11]*w,T[12]=u[12],T[13]=u[13],T[14]=u[14],T[15]=u[15],T}function rotateX(T,u,h){var g=Math.sin(h),v=Math.cos(h),w=u[4],C=u[5],k=u[6],U=u[7],N=u[8],O=u[9],d=u[10],M=u[11];return u!==T&&(T[0]=u[0],T[1]=u[1],T[2]=u[2],T[3]=u[3],T[12]=u[12],T[13]=u[13],T[14]=u[14],T[15]=u[15]),T[4]=w*v+N*g,T[5]=C*v+O*g,T[6]=k*v+d*g,T[7]=U*v+M*g,T[8]=N*v-w*g,T[9]=O*v-C*g,T[10]=d*v-k*g,T[11]=M*v-U*g,T}function rotateZ(T,u,h){var g=Math.sin(h),v=Math.cos(h),w=u[0],C=u[1],k=u[2],U=u[3],N=u[4],O=u[5],d=u[6],M=u[7];return u!==T&&(T[8]=u[8],T[9]=u[9],T[10]=u[10],T[11]=u[11],T[12]=u[12],T[13]=u[13],T[14]=u[14],T[15]=u[15]),T[0]=w*v+N*g,T[1]=C*v+O*g,T[2]=k*v+d*g,T[3]=U*v+M*g,T[4]=N*v-w*g,T[5]=O*v-C*g,T[6]=d*v-k*g,T[7]=M*v-U*g,T}function fromRotation(T,u,h){var g=h[0],v=h[1],w=h[2],C=Math.hypot(g,v,w),k,U,N;return C<EPSILON?null:(C=1/C,g*=C,v*=C,w*=C,k=Math.sin(u),U=Math.cos(u),N=1-U,T[0]=g*g*N+U,T[1]=v*g*N+w*k,T[2]=w*g*N-v*k,T[3]=0,T[4]=g*v*N-w*k,T[5]=v*v*N+U,T[6]=w*v*N+g*k,T[7]=0,T[8]=g*w*N+v*k,T[9]=v*w*N-g*k,T[10]=w*w*N+U,T[11]=0,T[12]=0,T[13]=0,T[14]=0,T[15]=1,T)}function orthoNO(T,u,h,g,v,w,C){var k=1/(u-h),U=1/(g-v),N=1/(w-C);return T[0]=-2*k,T[1]=0,T[2]=0,T[3]=0,T[4]=0,T[5]=-2*U,T[6]=0,T[7]=0,T[8]=0,T[9]=0,T[10]=2*N,T[11]=0,T[12]=(u+h)*k,T[13]=(v+g)*U,T[14]=(C+w)*N,T[15]=1,T}var ortho=orthoNO;function multiplyScalar(T,u,h){return T[0]=u[0]*h,T[1]=u[1]*h,T[2]=u[2]*h,T[3]=u[3]*h,T[4]=u[4]*h,T[5]=u[5]*h,T[6]=u[6]*h,T[7]=u[7]*h,T[8]=u[8]*h,T[9]=u[9]*h,T[10]=u[10]*h,T[11]=u[11]*h,T[12]=u[12]*h,T[13]=u[13]*h,T[14]=u[14]*h,T[15]=u[15]*h,T}var mul=multiply;function create$2(){var T=new ARRAY_TYPE(3);return ARRAY_TYPE!=Float32Array&&(T[0]=0,T[1]=0,T[2]=0),T}function clone$1(T){var u=new ARRAY_TYPE(3);return u[0]=T[0],u[1]=T[1],u[2]=T[2],u}function length$1(T){var u=T[0],h=T[1],g=T[2];return Math.hypot(u,h,g)}function fromValues$2(T,u,h){var g=new ARRAY_TYPE(3);return g[0]=T,g[1]=u,g[2]=h,g}function copy(T,u){return T[0]=u[0],T[1]=u[1],T[2]=u[2],T}function add$1(T,u,h){return T[0]=u[0]+h[0],T[1]=u[1]+h[1],T[2]=u[2]+h[2],T}function subtract$1(T,u,h){return T[0]=u[0]-h[0],T[1]=u[1]-h[1],T[2]=u[2]-h[2],T}function min$j(T,u,h){return T[0]=Math.min(u[0],h[0]),T[1]=Math.min(u[1],h[1]),T[2]=Math.min(u[2],h[2]),T}function max$l(T,u,h){return T[0]=Math.max(u[0],h[0]),T[1]=Math.max(u[1],h[1]),T[2]=Math.max(u[2],h[2]),T}function scale$2(T,u,h){return T[0]=u[0]*h,T[1]=u[1]*h,T[2]=u[2]*h,T}function negate(T,u){return T[0]=-u[0],T[1]=-u[1],T[2]=-u[2],T}function normalize$1(T,u){var h=u[0],g=u[1],v=u[2],w=h*h+g*g+v*v;return w>0&&(w=1/Math.sqrt(w)),T[0]=u[0]*w,T[1]=u[1]*w,T[2]=u[2]*w,T}function dot(T,u){return T[0]*u[0]+T[1]*u[1]+T[2]*u[2]}function cross(T,u,h){var g=u[0],v=u[1],w=u[2],C=h[0],k=h[1],U=h[2];return T[0]=v*U-w*k,T[1]=w*C-g*U,T[2]=g*k-v*C,T}function lerp(T,u,h,g){var v=u[0],w=u[1],C=u[2];return T[0]=v+g*(h[0]-v),T[1]=w+g*(h[1]-w),T[2]=C+g*(h[2]-C),T}function angle(T,u){var h=T[0],g=T[1],v=T[2],w=u[0],C=u[1],k=u[2],U=Math.sqrt(h*h+g*g+v*v),N=Math.sqrt(w*w+C*C+k*k),O=U*N,d=O&&dot(T,u)/O;return Math.acos(Math.min(Math.max(d,-1),1))}var sub$1=subtract$1,len=length$1;(function(){var T=create$2();return function(u,h,g,v,w,C){var k,U;for(h||(h=3),g||(g=0),v?U=Math.min(v*h+g,u.length):U=u.length,k=g;k<U;k+=h)T[0]=u[k],T[1]=u[k+1],T[2]=u[k+2],w(T,T,C),u[k]=T[0],u[k+1]=T[1],u[k+2]=T[2];return u}})();function create$1(){var T=new ARRAY_TYPE(4);return ARRAY_TYPE!=Float32Array&&(T[0]=0,T[1]=0,T[2]=0,T[3]=0),T}function clone(T){var u=new ARRAY_TYPE(4);return u[0]=T[0],u[1]=T[1],u[2]=T[2],u[3]=T[3],u}function fromValues$1(T,u,h,g){var v=new ARRAY_TYPE(4);return v[0]=T,v[1]=u,v[2]=h,v[3]=g,v}function add(T,u,h){return T[0]=u[0]+h[0],T[1]=u[1]+h[1],T[2]=u[2]+h[2],T[3]=u[3]+h[3],T}function subtract(T,u,h){return T[0]=u[0]-h[0],T[1]=u[1]-h[1],T[2]=u[2]-h[2],T[3]=u[3]-h[3],T}function scale$1(T,u,h){return T[0]=u[0]*h,T[1]=u[1]*h,T[2]=u[2]*h,T[3]=u[3]*h,T}function transformMat4(T,u,h){var g=u[0],v=u[1],w=u[2],C=u[3];return T[0]=h[0]*g+h[4]*v+h[8]*w+h[12]*C,T[1]=h[1]*g+h[5]*v+h[9]*w+h[13]*C,T[2]=h[2]*g+h[6]*v+h[10]*w+h[14]*C,T[3]=h[3]*g+h[7]*v+h[11]*w+h[15]*C,T}var sub=subtract;(function(){var T=create$1();return function(u,h,g,v,w,C){var k,U;for(h||(h=4),g||(g=0),v?U=Math.min(v*h+g,u.length):U=u.length,k=g;k<U;k+=h)T[0]=u[k],T[1]=u[k+1],T[2]=u[k+2],T[3]=u[k+3],w(T,T,C),u[k]=T[0],u[k+1]=T[1],u[k+2]=T[2],u[k+3]=T[3];return u}})();function create(){var T=new ARRAY_TYPE(2);return ARRAY_TYPE!=Float32Array&&(T[0]=0,T[1]=0),T}function fromValues(T,u){var h=new ARRAY_TYPE(2);return h[0]=T,h[1]=u,h}function scale(T,u,h){return T[0]=u[0]*h,T[1]=u[1]*h,T}function length(T){var u=T[0],h=T[1];return Math.hypot(u,h)}function normalize(T,u){var h=u[0],g=u[1],v=h*h+g*g;return v>0&&(v=1/Math.sqrt(v)),T[0]=u[0]*v,T[1]=u[1]*v,T}(function(){var T=create();return function(u,h,g,v,w,C){var k,U;for(h||(h=2),g||(g=0),v?U=Math.min(v*h+g,u.length):U=u.length,k=g;k<U;k+=h)T[0]=u[k],T[1]=u[k+1],w(T,T,C),u[k]=T[0],u[k+1]=T[1];return u}})();const version="0.43.3",Nt=class Nt{constructor({name:u="niivue",level:h="info"}={}){g0(this,"level");g0(this,"name");this.name=`${u}`,this.level=h}debug(...u){Nt.levels[this.level]>Nt.levels.debug||console.debug(`${this.name}-debug`,...u)}info(...u){Nt.levels[this.level]>Nt.levels.info||console.info(`${this.name}-info`,...u)}warn(...u){Nt.levels[this.level]>Nt.levels.warn||console.warn(`${this.name}-warn`,...u)}error(...u){Nt.levels[this.level]>Nt.levels.error||console.error(`${this.name}-error`,...u)}fatal(...u){Nt.levels[this.level]>Nt.levels.fatal||console.error(`${this.name}-fatal`,...u)}setLogLevel(u){this.level=u}setName(u){this.name=u}};g0(Nt,"levels",{debug:0,info:1,warn:2,error:3,fatal:4,silent:1/0});let Log=Nt;const log=new Log({name:"niivue",level:"info"}),compileShader=function(T,u,h){const g=T.createShader(T.VERTEX_SHADER);if(g===null)throw new Error("could not create vertex shader");if(T.shaderSource(g,u),T.compileShader(g),!T.getShaderParameter(g,T.COMPILE_STATUS))throw log.error(T.getShaderInfoLog(g)),new Error("Vertex shader failed to compile, see console for log");const v=T.createShader(T.FRAGMENT_SHADER);if(v===null)throw new Error("could not create fragment shader");if(T.shaderSource(v,h),T.compileShader(v),!T.getShaderParameter(v,T.COMPILE_STATUS))throw log.error(T.getShaderInfoLog(v)),new Error("Fragment shader failed to compile, see console for log");const w=T.createProgram();if(w===null)throw new Error("could not create GL program");if(T.attachShader(w,g),T.attachShader(w,v),T.linkProgram(w),!T.getProgramParameter(w,T.LINK_STATUS))throw log.error(T.getProgramInfoLog(w)),new Error("Shader failed to link, see console for log");return w};class Shader{constructor(u,h,g){g0(this,"program");g0(this,"uniforms",{});g0(this,"isMatcap");this.program=compileShader(u,h,g);const v=/uniform[^;]+[ ](\w+);/g,w=/uniform[^;]+[ ](\w+);/,C=h.match(v),k=g.match(v);C&&C.forEach(U=>{const N=U.match(w);this.uniforms[N[1]]=-1}),k&&k.forEach(U=>{const N=U.match(w);this.uniforms[N[1]]=-1});for(const U in this.uniforms)this.uniforms[U]=u.getUniformLocation(this.program,U)}use(u){u.useProgram(this.program)}}const vertRenderShader=`#version 300 es
2
2
  #line 4
3
3
  layout(location=0) in vec3 pos;
4
4
  layout(location=1) in vec3 texCoords;
@@ -1611,9 +1611,9 @@ If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more in
1611
1611
  `),N=N.replace(/(?:\r\n|\r|\n)/g,"<br />"),N},u.Image.prototype.getPalleteValues=function(C){var k,U,N,O,d,M,e,b,z,W,s0;if(k=null,U=null,N=u.Image.getValueSafely(this.getTag(C[0],C[1])),N!==null){for(O=N.buffer.byteLength/2,k=[],U=[],d=0;d<O;d+=1)k[d]=N.getUint16(d*2,!1)&65535,U[d]=N.getUint16(d*2,!0)&65535;return M=Math.max.apply(Math,k),e=Math.min.apply(Math,k),b=Math.max.apply(Math,U),z=Math.min.apply(Math,U),W=Math.abs(M-e),s0=Math.abs(b-z),W<s0?this.scalePalette(k):this.scalePalette(U)}return null},u.Image.prototype.scalePalette=function(C){var k,U,N,O,d;if(U=Math.max.apply(Math,C),k=Math.min.apply(Math,C),U>255||k<0)for(O=255/(U-k),d=k,N=0;N<C.length;N+=1)C[N]=parseInt(Math.round((C[N]-d)*O));return C},T.exports&&(T.exports=u.Image)}(image)),image.exports}var iterator={exports:{}},hasRequiredIterator;function requireIterator(){return hasRequiredIterator||(hasRequiredIterator=1,function(T){var u=u||{};u.OrderedMapIterator=u.OrderedMapIterator||function(h){this.orderedMap=h,this.index=0},u.OrderedMapIterator.prototype.hasNext=function(){return this.index<this.orderedMap.orderedKeys.length},u.OrderedMapIterator.prototype.next=function(){var h=this.orderedMap.get(this.orderedMap.orderedKeys[this.index]);return this.index+=1,h},T.exports&&(T.exports=u.OrderedMapIterator)}(iterator)),iterator.exports}var orderedmap={exports:{}},hasRequiredOrderedmap;function requireOrderedmap(){return hasRequiredOrderedmap||(hasRequiredOrderedmap=1,function(T){var u=u||{};u.OrderedMapIterator=u.OrderedMapIterator||(typeof commonjsRequire<"u"?requireIterator():null),u.OrderedMap=u.OrderedMap||function(){this.map={},this.orderedKeys=[]},u.OrderedMap.prototype.put=function(h,g){h in this.map?this.map[h]=g:(this.orderedKeys.push(h),this.orderedKeys.sort(function(v,w){return parseFloat(v)-parseFloat(w)}),this.map[h]=g)},u.OrderedMap.prototype.remove=function(h){var g=this.orderedKeys.indexOf(h);if(g===-1)throw new Error("key does not exist");this.orderedKeys.splice(g,1),delete this.map[h]},u.OrderedMap.prototype.get=function(h){return h in this.map?this.map[h]:null},u.OrderedMap.prototype.iterator=function(){return new u.OrderedMapIterator(this)},u.OrderedMap.prototype.getOrderedValues=function(){for(var h=[],g=this.iterator();g.hasNext();)h.push(g.next());return h},T.exports&&(T.exports=u.OrderedMap)}(orderedmap)),orderedmap.exports}var series={exports:{}},hasRequiredSeries;function requireSeries(){return hasRequiredSeries||(hasRequiredSeries=1,function(T){var u=u||{};u.Parser=u.Parser||(typeof commonjsRequire<"u"?requireParser():null),u.Image=u.Image||(typeof commonjsRequire<"u"?requireImage():null),u.OrderedMap=u.OrderedMap||(typeof commonjsRequire<"u"?requireOrderedmap():null),u.OrderedMapIterator=u.OrderedMapIterator||(typeof commonjsRequire<"u"?requireIterator():null),u.Utils=u.Utils||(typeof commonjsRequire<"u"?requireUtilities():null),u.Series=u.Series||function(){this.images=[],this.imagesOriginalOrder=null,this.isMosaic=!1,this.isElscint=!1,this.isCompressed=!1,this.numberOfFrames=0,this.numberOfFramesInFile=0,this.isMultiFrame=!1,this.isMultiFrameVolume=!1,this.isMultiFrameTimeseries=!1,this.isImplicitTimeseries=!1,this.sliceSense=!1,this.sliceDir=u.Image.SLICE_DIRECTION_UNKNOWN,this.error=null},u.Series.parserError=null,u.Series.useExplicitOrdering=!1,u.Series.useExplicitSpacing=0,u.Series.parseImage=function(h){var g,v;return g=new u.Parser,v=g.parse(h),g.hasError()?(u.Series.parserError=g.error,null):(g.inflated&&(v.inflated=g.inflated),v)},u.Series.getMosaicOffset=function(h,g,v,w,C,k,U){var N,O,d;return N=C,O=k,d=U,N=d%h*g+N,O=(parseInt(d/h)*v+O)*w,N+O},u.Series.orderDicoms=function(h,g,v){var w,C,k,U,N,O,d,M,e,b;for(w=h[0].getImagePosition()!==null,C=h[0].getSliceLocation()!==null,k=h[0].getImageNumber()!==null,U=u.Series.orderByTime(h,g,v,w,C),N=U.orderedKeys,b=[],O=0;O<N.length;O+=1)for(M=U.get(N[O]),w?e=u.Series.orderByImagePosition(M,v):C?e=u.Series.orderBySliceLocation(M):k?e=u.Series.orderByImageNumber(M):e=M,d=0;d<e.length;d+=1)b.push(e[d]);for(d=0;d<b.length;d+=1)b[d].index=d;return b},u.Series.orderByImagePosition=function(h,g){var v,w;for(v=new u.OrderedMap,w=0;w<h.length;w+=1)v.put(h[w].getImagePositionSliceDir(g),h[w]);return v.getOrderedValues()},u.Series.orderBySliceLocation=function(h){var g,v;for(g=new u.OrderedMap,v=0;v<h.length;v+=1)g.put(h[v].getSliceLocation(),h[v]);return g.getOrderedValues()},u.Series.orderByImageNumber=function(h){var g,v;for(g=new u.OrderedMap,v=0;v<h.length;v+=1)g.put(h[v].getImageNumber(),h[v]);return g.getOrderedValues()},u.Series.hasMatchingSlice=function(h,g,v,w,C){var k=0,U,N,O,d,M;for(w?k=g.getImagePositionSliceDir(v):C?k=g.getSliceLocation():k=g.getImageNumber(),U=0;U<h.length;U+=1)if(N=h[U],w){if(O=N.getImagePositionSliceDir(v),O===k)return!0}else if(C){if(d=N.getSliceLocation(),d===k)return!0}else if(M=N.getImageNumber(),M===k)return!0;return!1},u.Series.orderByTime=function(h,g,v,w,C){var k,U,N,O,d,M,e,b,z,W,s0,K,J,D,Z,X;if(k=new u.OrderedMap,U=g>1&&h[0].getTemporalPosition()!==null,N=g>1&&h[0].getTemporalNumber()!==null&&h[0].getTemporalNumber()===g,U&&N)for(O=0;O<h.length;O+=1)d=h[O],M=d.getTemporalPosition(),e=k.get(M),e||(e=[],k.put(M,e)),e.push(d);else{for(b=new u.OrderedMap,O=0;O<h.length;O+=1)h[O]!==null&&(h[O].getImageNumber(),z=O,w?z=h[O].getImagePositionSliceDir(v):C&&(z=h[O].getSliceLocation()),W=b.get(z),W===null&&(W=new u.OrderedMap,b.put(z,W)),W.put(O,h[O]));for(s0=[],K=0,J=b.iterator();J.hasNext();)for(W=J.next(),D=W.iterator();D.hasNext();)s0[K]=D.next(),K+=1;for(O=0;O<s0.length;O+=1)if(s0[O]!==null){for(Z=null,X=k.iterator();X.hasNext();)if(e=X.next(),!u.Series.hasMatchingSlice(e,s0[O],v,w,C)){Z=e;break}Z===null&&(Z=[],k.put(k.orderedKeys.length,Z)),Z.push(s0[O])}}return k},u.Series.prototype.getOrder=function(){var h,g=[];for(h=0;h<this.imagesOriginalOrder.length;h+=1)g[h]=this.imagesOriginalOrder[h].index;return g},u.Series.prototype.toString=function(){return this.images[0].getSeriesId()},u.Series.prototype.getName=function(){var h=this.images[0].getSeriesDescription(),g=this.images[0].getSeriesInstanceUID();return h!==null?h:g!==null?g:null},u.Series.prototype.addImage=function(h){this.images.push(h)},u.Series.prototype.matchesSeries=function(h){return this.images.length===0?!0:this.images[0].getSeriesId()===h.getSeriesId()},u.Series.prototype.buildSeries=function(){var h,g,v,w,C,k,U,N,O,d;if(this.isMosaic=this.images[0].isMosaic(),this.isElscint=this.images[0].isElscint(),this.isCompressed=this.images[0].isCompressed(),this.numberOfFrames=this.images[0].getNumberOfFrames(),this.numberOfFramesInFile=this.images[0].getNumberOfImplicitFrames(),this.isMultiFrame=this.numberOfFrames>1||this.isMosaic&&this.images[0].length>1,this.isMultiFrameVolume=!1,this.isMultiFrameTimeseries=!1,this.isImplicitTimeseries=!1,this.isMultiFrame&&(h=this.images[0].getFrameTime()>0,this.isMosaic?this.isMultiFrameTimeseries=!0:h?this.isMultiFrameTimeseries=!0:this.numberOfFramesInFile>1?(this.isMultiFrameTimeseries=!0,this.numberOfFrames=this.images.length):this.isMultiFrameVolume=!0),!this.isMosaic&&this.numberOfFrames<=1){for(d=this.images[0].getImagePosition()||[],v=d.toString(),this.numberOfFrames=0,g=0;g<this.images.length;g+=1)d=this.images[g].getImagePosition()||[],d.toString()===v&&(this.numberOfFrames+=1);this.numberOfFrames>1&&(this.isImplicitTimeseries=!0)}this.sliceDir=this.images[0].getAcquiredSliceDirection(),u.Series.useExplicitOrdering?w=this.images.slice():w=u.Series.orderDicoms(this.images,this.numberOfFrames,this.sliceDir),C=w[0].getImagePositionSliceDir(this.sliceDir),k=w[w.length-1].getImagePositionSliceDir(this.sliceDir),U=k-C,u.Series.useExplicitOrdering?this.sliceSense=!1:this.isMosaic?this.sliceSense=!0:this.isMultiFrame?(N=w[0].getSliceLocationVector(),N!==null?(O=w[0].getOrientation(),O.charAt(2)==="Z"?this.sliceSense=N[0]-N[N.length-1]<0:this.sliceSense=N[0]-N[N.length-1]>0):this.sliceSense=!(C<0)):this.sliceDir===u.Image.SLICE_DIRECTION_SAGITTAL||this.sliceDir===u.Image.SLICE_DIRECTION_CORONAL?U>0?this.sliceSense=!1:this.sliceSense=!0:U>0?this.sliceSense=!0:this.sliceSense=!1,this.imagesOriginalOrder=this.images,this.images=w},u.Series.prototype.concatenateImageData=function(h,g){var v,w,C;this.isMosaic?w=this.getMosaicData(this.images[0],this.images[0].getPixelDataBytes()):w=this.images[0].getPixelDataBytes(),C=this.validatePixelDataLength(this.images[0]),this.images[0].clearPixelData(),v=new Uint8Array(new ArrayBuffer(C*this.images.length)),v.set(new Uint8Array(w,0,C),0),setTimeout(u.Utils.bind(this,function(){this.concatenateNextImageData(v,C,h,1,g)}),0)},u.Series.prototype.concatenateNextImageData=function(h,g,v,w,C){var k,U;w>=this.images.length?(v&&v.drawProgress(1,"Reading DICOM Images"),C(h.buffer)):(v&&v.drawProgress(w/this.images.length,"Reading DICOM Images"),this.isMosaic?k=this.getMosaicData(this.images[w],this.images[w].getPixelDataBytes()):k=this.images[w].getPixelDataBytes(),U=this.validatePixelDataLength(this.images[w]),this.images[w].clearPixelData(),h.set(new Uint8Array(k,0,U),g*w),setTimeout(u.Utils.bind(this,function(){this.concatenateNextImageData(h,g,v,w+1,C)}),0))},u.Series.prototype.validatePixelDataLength=function(h){var g=h.getPixelDataBytes().byteLength,v=h.getCols()*h.getRows();return g%v===0?g:v*h.getNumberOfFrames()*h.getNumberOfSamplesPerPixel()*(h.getBitsAllocated()/8)},u.Series.prototype.getMosaicData=function(h,g){var v,w,C,k,U,N,O,d,M,e,b,z,W,s0,K,J,D,Z=0;for(O=parseInt(this.images[0].getBitsAllocated()/8),b=this.images[0].getMosaicCols()*this.images[0].getMosaicRows(),z=parseInt(this.images[0].getRows()/this.images[0].getMosaicRows()),W=parseInt(this.images[0].getCols()/this.images[0].getMosaicCols()),v=this.images[0].getCols(),w=this.images[0].getRows(),C=this.images[0].getMosaicRows(),k=this.images[0].getMosaicCols(),U=parseInt(w/C),N=parseInt(v/k),s0=new Uint8Array(new ArrayBuffer(b*z*W*O)),K=new Uint8Array(g),d=0;d<b;d+=1)for(M=0;M<z;M+=1)for(e=0;e<W;e+=1)for(J=u.Series.getMosaicOffset(k,N,U,v,e,M,d),D=0;D<O;D+=1)s0[Z]=K[J*O+D],Z+=1;return s0.buffer},T.exports&&(T.exports=u.Series)}(series)),series.exports}(function(T){var u=u||{};u.CompressionUtils=u.CompressionUtils||(typeof commonjsRequire<"u"?requireCompressionUtils():null),u.Dictionary=u.Dictionary||(typeof commonjsRequire<"u"?requireDictionary():null),u.Image=u.Image||(typeof commonjsRequire<"u"?requireImage():null),u.OrderedMapIterator=u.OrderedMapIterator||(typeof commonjsRequire<"u"?requireIterator():null),u.OrderedMap=u.OrderedMap||(typeof commonjsRequire<"u"?requireOrderedmap():null),u.Parser=u.Parser||(typeof commonjsRequire<"u"?requireParser():null),u.RLE=u.RLE||(typeof commonjsRequire<"u"?requireRle():null),u.Series=u.Series||(typeof commonjsRequire<"u"?requireSeries():null),u.Tag=u.Tag||(typeof commonjsRequire<"u"?requireTag():null),u.Utils=u.Utils||(typeof commonjsRequire<"u"?requireUtilities():null),u.Siemens=u.Siemens||(typeof commonjsRequire<"u"?requireSiemens():null);var h=h||{};h.lossless=h.lossless||{},h.lossless.Decoder=typeof commonjsRequire<"u"?requireMain():null;var g=g||(typeof commonjsRequire<"u"?requireJpegBaseline().JpegImage:null),v=v||(typeof commonjsRequire<"u"?requireJpx():null),w=w||(typeof commonjsRequire<"u"?requireCharLSDynamicMemoryBrowser():null),C=C||(typeof commonjsRequire<"u"?requireJpegLs():null),k=k||(typeof commonjsRequire<"u"?requirePako():null);T.exports&&(T.exports=u)})(main$1);var mainExports=main$1.exports;const daikon=getDefaultExportFromCjs(mainExports),isPlatformLittleEndian=()=>{const T=new ArrayBuffer(2);return new DataView(T).setInt16(0,256,!0),new Int16Array(T)[0]===256};var NiiDataType=(T=>(T[T.DT_NONE=0]="DT_NONE",T[T.DT_BINARY=1]="DT_BINARY",T[T.DT_UINT8=2]="DT_UINT8",T[T.DT_INT16=4]="DT_INT16",T[T.DT_INT32=8]="DT_INT32",T[T.DT_FLOAT32=16]="DT_FLOAT32",T[T.DT_COMPLEX64=32]="DT_COMPLEX64",T[T.DT_FLOAT64=64]="DT_FLOAT64",T[T.DT_RGB24=128]="DT_RGB24",T[T.DT_INT8=256]="DT_INT8",T[T.DT_UINT16=512]="DT_UINT16",T[T.DT_UINT32=768]="DT_UINT32",T[T.DT_INT64=1024]="DT_INT64",T[T.DT_UINT64=1280]="DT_UINT64",T[T.DT_FLOAT128=1536]="DT_FLOAT128",T[T.DT_COMPLEX128=1792]="DT_COMPLEX128",T[T.DT_COMPLEX256=2048]="DT_COMPLEX256",T[T.DT_RGBA32=2304]="DT_RGBA32",T))(NiiDataType||{}),NiiIntentCode=(T=>(T[T.NIFTI_INTENT_LABEL=1002]="NIFTI_INTENT_LABEL",T[T.NIFTI_INTENT_VECTOR=1007]="NIFTI_INTENT_VECTOR",T[T.NIFTI_INTENT_RGB_VECTOR=2003]="NIFTI_INTENT_RGB_VECTOR",T))(NiiIntentCode||{}),ImageType=(T=>(T[T.UNKNOWN=0]="UNKNOWN",T[T.NII=1]="NII",T[T.DCM=2]="DCM",T[T.DCM_MANIFEST=3]="DCM_MANIFEST",T[T.MIH=4]="MIH",T[T.MIF=5]="MIF",T[T.NHDR=6]="NHDR",T[T.NRRD=7]="NRRD",T[T.MHD=8]="MHD",T[T.MHA=9]="MHA",T[T.MGH=10]="MGH",T[T.MGZ=11]="MGZ",T[T.V=12]="V",T[T.V16=13]="V16",T[T.VMR=14]="VMR",T[T.HEAD=15]="HEAD",T[T.DCM_FOLDER=16]="DCM_FOLDER",T))(ImageType||{});const NVIMAGE_TYPE=Object.freeze({...ImageType,parse:T=>{let u=0;switch(T.toUpperCase()){case"":case"DCM":u=2;break;case"TXT":u=3;break;case"NII":u=1;break;case"MIH":u=4;break;case"MIF":u=5;break;case"NHDR":u=6;break;case"NRRD":u=7;break;case"MHD":u=8;break;case"MHA":u=9;break;case"MGH":u=10;break;case"MGZ":u=11;break;case"V":u=12;break;case"V16":u=13;break;case"VMR":u=14;break;case"HEAD":u=15;break}return u}}),NVImageFromUrlOptions=(T,u="",h="",g="gray",v=1,w=NaN,C=NaN,k=!0,U=.02,N=!1,O=!1,d="",M=0,e=NVIMAGE_TYPE.UNKNOWN,b=NaN,z=NaN,W=!0,s0=!1,K=null)=>({url:T,urlImageData:u,name:h,colormap:g,colorMap:g,opacity:v,cal_min:w,cal_max:C,trustCalMinMax:k,percentileFrac:U,ignoreZeroVoxels:N,useQFormNotSForm:O,colormapNegative:d,imageType:e,cal_minNeg:b,cal_maxNeg:z,colorbarVisible:W,frame4D:M,alphaThreshold:s0,colormapLabel:K});function getBestTransform(T,u,h){const g=T;let v=null;if(g){const w={colSize:u[0],rowSize:u[1],sliceSize:u[2]},C=h,k=[g[0],g[1],g[2]],U=[g[3],g[4],g[5]],N=[k[1]*U[2]-k[2]*U[1],k[2]*U[0]-k[0]*U[2],k[0]*U[1]-k[1]*U[0]];v=[[k[0]*w.colSize*-1,U[0]*w.rowSize*-1,N[0]*w.sliceSize*-1,-1*C[0]],[k[1]*w.colSize*-1,U[1]*w.rowSize*-1,N[1]*w.sliceSize*-1,-1*C[1]],[k[2]*w.colSize,U[2]*w.rowSize,N[2]*w.sliceSize,C[2]],[0,0,0,1]]}return v}function str2Buffer(T){const u=[];for(let h=0;h<T.length;h++){const g=T.charCodeAt(h);u.push(g&255)}return u}function hdrToArrayBuffer(T,u=!1){const v=new Uint8Array(348),w=new DataView(v.buffer);w.setInt32(0,348,T.littleEndian),w.setUint8(39,T.dim_info);for(let k=0;k<8;k++)w.setUint16(40+2*k,T.dims[k],T.littleEndian);w.setFloat32(56,T.intent_p1,T.littleEndian),w.setFloat32(60,T.intent_p2,T.littleEndian),w.setFloat32(64,T.intent_p3,T.littleEndian),w.setInt16(68,T.intent_code,T.littleEndian),u?(w.setInt16(70,2,T.littleEndian),w.setInt16(72,8,T.littleEndian)):(w.setInt16(70,T.datatypeCode,T.littleEndian),w.setInt16(72,T.numBitsPerVoxel,T.littleEndian)),w.setInt16(74,T.slice_start,T.littleEndian);for(let k=0;k<8;k++)w.setFloat32(76+4*k,T.pixDims[k],T.littleEndian);u?(w.setFloat32(108,352,T.littleEndian),w.setFloat32(112,1,T.littleEndian),w.setFloat32(116,0,T.littleEndian)):(w.setFloat32(108,T.vox_offset,T.littleEndian),w.setFloat32(112,T.scl_slope,T.littleEndian),w.setFloat32(116,T.scl_inter,T.littleEndian)),w.setInt16(120,T.slice_end,T.littleEndian),w.setUint8(122,T.slice_code),w.setUint8(123,T.xyzt_units),u?(w.setFloat32(124,0,T.littleEndian),w.setFloat32(128,0,T.littleEndian)):(w.setFloat32(124,T.cal_max,T.littleEndian),w.setFloat32(128,T.cal_min,T.littleEndian)),w.setFloat32(132,T.slice_duration,T.littleEndian),w.setFloat32(136,T.toffset,T.littleEndian),v.set(str2Buffer(T.description),148),v.set(str2Buffer(T.aux_file),228),w.setInt16(252,T.qform_code,T.littleEndian),w.setInt16(254,T.sform_code,T.littleEndian),w.setFloat32(256,T.quatern_b,T.littleEndian),w.setFloat32(260,T.quatern_c,T.littleEndian),w.setFloat32(264,T.quatern_d,T.littleEndian),w.setFloat32(268,T.qoffset_x,T.littleEndian),w.setFloat32(272,T.qoffset_y,T.littleEndian),w.setFloat32(276,T.qoffset_z,T.littleEndian);const C=T.affine.flat();for(let k=0;k<12;k++)w.setFloat32(280+4*k,C[k],T.littleEndian);return v.set(str2Buffer(T.intent_name),328),v.set(str2Buffer(T.magic),344),v}function getExtents(T,u=!0){const h=Math.round(T.length/3),g=fromValues$2(0,0,0),v=create$2(),w=create$2();let C=0,k=1;u&&(k=2);for(let d=0;d<k;d++){C=0;for(let e=0;e<h;e++){const b=fromValues$2(T[e*3],T[e*3+1],T[e*3+2]);e===0&&(copy(v,b),copy(w,b)),min$j(v,v,b),max$l(w,w,b),subtract$1(b,b,g);const z=len(b);C=Math.max(C,z)}if(d+1>=k)break;let M=!0;for(let e=0;e<3;++e)v[e]>g[e]&&(M=!1),w[e]<g[e]&&(M=!1);if(M)break;lerp(g,v,w,.5),log.debug("origin moved inside volume: ",g)}const U=[v[0],v[1],v[2]],N=[w[0],w[1],w[2]];return{min:U,max:N,furthestVertexFromOrigin:C,origin:g}}function isAffineOK(T){const u=[!1,!1,!1,!1],h=[!1,!1,!1,!1];for(let g=0;g<4;g++)for(let v=0;v<4;v++)if(isNaN(T[g][v]))return!1;for(let g=0;g<3;g++)for(let v=0;v<3;v++)T[g][v]!==0&&(u[g]=!0,h[v]=!0);for(let g=0;g<3;g++)if(!u[g]||!h[g])return!1;return!0}class NVImage{constructor(u=null,h="",g="gray",v=1,w=null,C=NaN,k=NaN,U=!0,N=.02,O=!1,d=!1,M="",e=0,b=NVIMAGE_TYPE.UNKNOWN,z=NaN,W=NaN,s0=!0,K=null){g0(this,"name");g0(this,"id");g0(this,"url");g0(this,"headers");g0(this,"_colormap");g0(this,"_opacity");g0(this,"percentileFrac");g0(this,"ignoreZeroVoxels");g0(this,"trustCalMinMax");g0(this,"colormapNegative");g0(this,"colormapLabel");g0(this,"colormapInvert");g0(this,"nFrame4D");g0(this,"frame4D");g0(this,"nTotalFrame4D");g0(this,"cal_minNeg");g0(this,"cal_maxNeg");g0(this,"colorbarVisible",!0);g0(this,"modulationImage",null);g0(this,"modulateAlpha",0);g0(this,"series",[]);g0(this,"nVox3D");g0(this,"oblique_angle");g0(this,"maxShearDeg");g0(this,"useQFormNotSForm");g0(this,"alphaThreshold");g0(this,"pixDims");g0(this,"matRAS");g0(this,"pixDimsRAS");g0(this,"obliqueRAS");g0(this,"dimsRAS");g0(this,"permRAS");g0(this,"img2RASstep");g0(this,"img2RASstart");g0(this,"toRAS");g0(this,"toRASvox");g0(this,"frac2mm");g0(this,"frac2mmOrtho");g0(this,"extentsMinOrtho");g0(this,"extentsMaxOrtho");g0(this,"mm2ortho");g0(this,"hdr",null);g0(this,"imageType");g0(this,"img");g0(this,"imaginary");g0(this,"fileObject");g0(this,"dims");g0(this,"onColormapChange",()=>{});g0(this,"onOpacityChange",()=>{});g0(this,"mm000");g0(this,"mm100");g0(this,"mm010");g0(this,"mm001");g0(this,"cal_min");g0(this,"cal_max");g0(this,"robust_min");g0(this,"robust_max");g0(this,"global_min");g0(this,"global_max");g0(this,"urlImgData");g0(this,"isManifest");g0(this,"limitFrames4D");if(this.name=h,this.id=v4(),this._colormap=g,this._opacity=v>1?1:v,this.percentileFrac=N,this.ignoreZeroVoxels=O,this.trustCalMinMax=U,this.colormapNegative=M,this.colormapLabel=K,this.frame4D=e,this.cal_minNeg=z,this.cal_maxNeg=W,this.colorbarVisible=s0,this.useQFormNotSForm=d,!u)return;const J=/(?:\.([^.]+))?$/;let D=J.exec(h)[1]||"";D=D.toUpperCase(),D==="GZ"&&(D=J.exec(h.slice(0,-3))[1],D=D.toUpperCase());let Z=null;switch(b===NVIMAGE_TYPE.UNKNOWN&&(b=NVIMAGE_TYPE.parse(D)),this.imageType=b,b){case NVIMAGE_TYPE.DCM_FOLDER:case NVIMAGE_TYPE.DCM_MANIFEST:case NVIMAGE_TYPE.DCM:Z=this.readDICOM(u);break;case NVIMAGE_TYPE.MIH:case NVIMAGE_TYPE.MIF:Z=this.readMIF(u,w);break;case NVIMAGE_TYPE.NHDR:case NVIMAGE_TYPE.NRRD:Z=this.readNRRD(u,w);break;case NVIMAGE_TYPE.MHD:case NVIMAGE_TYPE.MHA:Z=this.readMHA(u,w);break;case NVIMAGE_TYPE.MGH:case NVIMAGE_TYPE.MGZ:Z=this.readMGH(u);break;case NVIMAGE_TYPE.V:Z=this.readECAT(u);break;case NVIMAGE_TYPE.V16:Z=this.readV16(u);break;case NVIMAGE_TYPE.VMR:Z=this.readVMR(u);break;case NVIMAGE_TYPE.HEAD:Z=this.readHEAD(u,w);break;case NVIMAGE_TYPE.NII:this.hdr=nifti.readHeader(u),this.hdr!==null&&(this.hdr.cal_min===0&&this.hdr.cal_max===255&&(this.hdr.cal_max=0),nifti.isCompressed(u)?Z=nifti.readImage(this.hdr,nifti.decompress(u)):Z=nifti.readImage(this.hdr,u));break;default:throw new Error("Image type not supported")}if(this.hdr&&typeof this.hdr.magic=="number"&&(this.hdr.magic="n+1"),this.nFrame4D=1,this.hdr)for(let j=4;j<7;j++)this.hdr.dims[j]>1&&(this.nFrame4D*=this.hdr.dims[j]);if(this.frame4D=Math.min(this.frame4D,this.nFrame4D-1),this.nTotalFrame4D=this.nFrame4D,!this.hdr||!Z)return;this.nVox3D=this.hdr.dims[1]*this.hdr.dims[2]*this.hdr.dims[3];const X=this.nVox3D*(this.hdr.numBitsPerVoxel/8),r0=Z.byteLength/X;if(r0!==this.nFrame4D&&(r0>0&&r0*X===Z.byteLength?log.debug("Loading the first "+r0+" of "+this.nFrame4D+" volumes"):log.warn("This header does not match voxel data",this.hdr,Z.byteLength),this.nFrame4D=r0),(this.hdr.intent_code===NiiIntentCode.NIFTI_INTENT_VECTOR||this.hdr.intent_code===NiiIntentCode.NIFTI_INTENT_RGB_VECTOR)&&this.nFrame4D===3&&this.hdr.datatypeCode===NiiDataType.DT_FLOAT32){const f=new Float32Array(Z).slice();this.hdr.datatypeCode=NiiDataType.DT_RGBA32,this.nFrame4D=1;for(let x0=4;x0<7;x0++)this.hdr.dims[x0]=1;this.hdr.dims[0]=3,Z=new Uint8Array(this.nVox3D*4);let c0=1;for(let x0=0;x0<this.nVox3D*3;x0++)c0=Math.max(c0,Math.abs(f[x0]));const h0=255/c0,A0=this.nVox3D*2;let w0=0;for(let x0=0;x0<this.nVox3D;x0++){const C0=f[x0],E0=f[x0+this.nVox3D],M0=f[x0+A0];Z[w0]=Math.abs(C0*h0),Z[w0+1]=Math.abs(E0*h0),Z[w0+2]=Math.abs(M0*h0);const N0=+(C0>0)*1,oe=+(E0>0)*2,le=+(M0>0)*4;let Le=248+N0+oe+le;Math.abs(C0)+Math.abs(E0)+Math.abs(M0)<.1&&(Le=0),Z[w0+3]=Le,w0+=4}}(this.hdr.pixDims[1]===0||this.hdr.pixDims[2]===0||this.hdr.pixDims[3]===0)&&log.error("pixDims not plausible",this.hdr),(isNaN(this.hdr.scl_slope)||this.hdr.scl_slope===0)&&(this.hdr.scl_slope=1),isNaN(this.hdr.scl_inter)&&(this.hdr.scl_inter=0);let l0=isAffineOK(this.hdr.affine);if(d||!l0||this.hdr.qform_code>this.hdr.sform_code){log.debug("spatial transform based on QForm");const j=this.hdr.quatern_b,f=this.hdr.quatern_c,c0=this.hdr.quatern_d,h0=Math.sqrt(1-(Math.pow(j,2)+Math.pow(f,2)+Math.pow(c0,2))),A0=this.hdr.pixDims[0]===0?1:this.hdr.pixDims[0],w0=[[h0*h0+j*j-f*f-c0*c0,2*j*f-2*h0*c0,2*j*c0+2*h0*f],[2*j*f+2*h0*c0,h0*h0+f*f-j*j-c0*c0,2*f*c0-2*h0*j],[2*j*c0-2*h0*f,2*f*c0+2*h0*j,h0*h0+c0*c0-f*f-j*j]],x0=this.hdr.affine;for(let C0=0;C0<3;C0+=1)for(let E0=0;E0<3;E0+=1)x0[C0][E0]=w0[C0][E0]*this.hdr.pixDims[E0+1],E0===2&&(x0[C0][E0]*=A0);x0[0][3]=this.hdr.qoffset_x,x0[1][3]=this.hdr.qoffset_y,x0[2][3]=this.hdr.qoffset_z,this.hdr.affine=x0}if(l0=isAffineOK(this.hdr.affine),!l0){log.debug("Defective NIfTI: spatial transform does not make sense");let j=this.hdr.pixDims[1],f=this.hdr.pixDims[2],c0=this.hdr.pixDims[3];(isNaN(j)||j===0)&&(j=1),(isNaN(f)||f===0)&&(f=1),(isNaN(c0)||c0===0)&&(c0=1),this.hdr.pixDims[1]=j,this.hdr.pixDims[2]=f,this.hdr.pixDims[3]=c0;const h0=[[j,0,0,0],[0,f,0,0],[0,0,c0,0],[0,0,0,1]];this.hdr.affine=h0}if(this.hdr.datatypeCode!==NiiDataType.DT_RGB24&&this.hdr.datatypeCode!==NiiDataType.DT_RGBA32&&this.hdr.littleEndian!==isPlatformLittleEndian()&&this.hdr.numBitsPerVoxel>8){if(this.hdr.numBitsPerVoxel===16){const j=new Uint16Array(Z);for(let f=0;f<j.length;f++){const c0=j[f];j[f]=((c0&255)<<8|c0>>8&255)<<16>>16}}else if(this.hdr.numBitsPerVoxel===32){const j=new Uint32Array(Z);for(let f=0;f<j.length;f++){const c0=j[f];j[f]=(c0&255)<<24|(c0&65280)<<8|c0>>8&65280|c0>>24&255}}else if(this.hdr.numBitsPerVoxel===64){const j=this.hdr.numBitsPerVoxel/8,f=new Uint8Array(Z);for(let c0=0;c0<f.length;c0+=j){let h0=j-1;for(let A0=0;A0<h0;A0++){const w0=f[c0+A0];f[c0+A0]=f[c0+h0],f[c0+h0]=w0,h0--}}}}switch(this.hdr.datatypeCode){case NiiDataType.DT_UINT8:this.img=new Uint8Array(Z);break;case NiiDataType.DT_INT16:this.img=new Int16Array(Z);break;case NiiDataType.DT_FLOAT32:this.img=new Float32Array(Z);break;case NiiDataType.DT_FLOAT64:this.img=new Float64Array(Z);break;case NiiDataType.DT_RGB24:this.img=new Uint8Array(Z);break;case NiiDataType.DT_UINT16:this.img=new Uint16Array(Z);break;case NiiDataType.DT_RGBA32:this.img=new Uint8Array(Z);break;case NiiDataType.DT_INT8:{const j=new Int8Array(Z),f=j.length;this.img=new Int16Array(f);for(let c0=0;c0<f;c0++)this.img[c0]=j[c0];this.hdr.datatypeCode=NiiDataType.DT_INT16,this.hdr.numBitsPerVoxel=16;break}case NiiDataType.DT_BINARY:{const j=this.hdr.dims[1]*this.hdr.dims[2]*Math.max(1,this.hdr.dims[3])*Math.max(1,this.hdr.dims[4]),f=new Uint8Array(Z);this.img=new Uint8Array(j);const c0=new Uint8Array(8);for(let A0=0;A0<8;A0++)c0[A0]=Math.pow(2,A0);let h0=-1;for(let A0=0;A0<j;A0++){const w0=A0%8;w0===0&&h0++,f[h0]&c0[w0]&&(this.img[A0]=1)}this.hdr.datatypeCode=NiiDataType.DT_UINT8,this.hdr.numBitsPerVoxel=8;break}case NiiDataType.DT_UINT32:{const j=new Uint32Array(Z),f=j.length;this.img=new Float64Array(f);for(let c0=0;c0<f-1;c0++)this.img[c0]=j[c0];this.hdr.datatypeCode=NiiDataType.DT_FLOAT64;break}case NiiDataType.DT_INT32:{const j=new Int32Array(Z),f=j.length;this.img=new Float64Array(f);for(let c0=0;c0<f-1;c0++)this.img[c0]=j[c0];this.hdr.datatypeCode=NiiDataType.DT_FLOAT64;break}case NiiDataType.DT_INT64:{const j=new BigInt64Array(Z),f=j.length;this.img=new Float64Array(f);for(let c0=0;c0<f-1;c0++)this.img[c0]=Number(j[c0]);this.hdr.datatypeCode=NiiDataType.DT_FLOAT64;break}case NiiDataType.DT_COMPLEX64:{const j=new Float32Array(Z),f=Math.floor(j.length/2);this.imaginary=new Float32Array(f),this.img=new Float32Array(f);let c0=0;for(let h0=0;h0<f-1;h0++)this.img[h0]=j[c0],this.imaginary[h0]=j[c0+1],c0+=2;this.hdr.datatypeCode=NiiDataType.DT_FLOAT32;break}default:throw new Error("datatype "+this.hdr.datatypeCode+" not supported")}this.calculateRAS(),isNaN(C)||(this.hdr.cal_min=C),isNaN(k)||(this.hdr.cal_max=k),this.calMinMax()}computeObliqueAngle(u){const h=clone$2(u);transpose(h,u);const g=Math.sqrt(h[0]*h[0]+h[1]*h[1]+h[2]*h[2]),v=Math.max(Math.max(Math.abs(h[0]),Math.abs(h[1])),Math.abs(h[2]))/g,w=Math.sqrt(h[4]*h[4]+h[5]*h[5]+h[6]*h[6]),C=Math.max(Math.max(Math.abs(h[4]),Math.abs(h[5])),Math.abs(h[6]))/w,k=Math.sqrt(h[8]*h[8]+h[9]*h[9]+h[10]*h[10]),U=Math.max(Math.max(Math.abs(h[8]),Math.abs(h[9])),Math.abs(h[10]))/k,N=Math.min(Math.min(v,C),U);let O=Math.abs(Math.acos(N)*180/3.141592653);return O>.01?log.warn("Warning voxels not aligned with world space: "+O+` degrees from plumb.
1612
1612
  `):O=0,O}calculateOblique(){if(!this.matRAS)throw new Error("matRAS not defined");if(this.pixDimsRAS===void 0)throw new Error("pixDimsRAS not defined");if(!this.dimsRAS)throw new Error("dimsRAS not defined");this.oblique_angle=this.computeObliqueAngle(this.matRAS);const u=this.vox2mm([0,0,0],this.matRAS),h=this.vox2mm([1/this.pixDimsRAS[1],0,0],this.matRAS),g=this.vox2mm([0,1/this.pixDimsRAS[2],0],this.matRAS),v=this.vox2mm([0,0,1/this.pixDimsRAS[3]],this.matRAS);subtract$1(h,h,u),subtract$1(g,g,u),subtract$1(v,v,u);const w=fromValues$3(h[0],h[1],h[2],0,g[0],g[1],g[2],0,v[0],v[1],v[2],0,0,0,0,1);this.obliqueRAS=clone$2(w);const C=Math.abs(90-angle(h,g)*(180/Math.PI)),k=Math.abs(90-angle(h,v)*(180/Math.PI)),U=Math.abs(90-angle(g,v)*(180/Math.PI));this.maxShearDeg=Math.max(Math.max(C,k),U),this.maxShearDeg>.1&&log.warn("Warning: voxels are rhomboidal, maximum shear is %f degrees.",this.maxShearDeg);const N=fromValues$1(this.dimsRAS[1],this.dimsRAS[2],this.dimsRAS[3],1),O=clone$2(this.matRAS);transpose(O,O);const d=fromValues$1(-.5,-.5,-.5,0);translate(O,O,fromValues$2(d[0],d[1],d[2])),O[0]*=N[0],O[1]*=N[0],O[2]*=N[0],O[4]*=N[1],O[5]*=N[1],O[6]*=N[1],O[8]*=N[2],O[9]*=N[2],O[10]*=N[2],this.frac2mm=clone$2(O);const M=this.pixDimsRAS[1],e=this.pixDimsRAS[2],b=this.pixDimsRAS[3],z=clone$2(O);z[0]=M*N[0],z[1]=0,z[2]=0,z[4]=0,z[5]=e*N[1],z[6]=0,z[8]=0,z[9]=0,z[10]=b*N[2];const W=this.mm2vox([0,0,0],!0);z[12]=(-W[0]-.5)*M,z[13]=(-W[1]-.5)*e,z[14]=(-W[2]-.5)*b,this.frac2mmOrtho=clone$2(z),this.extentsMinOrtho=[z[12],z[13],z[14]],this.extentsMaxOrtho=[z[0]+z[12],z[5]+z[13],z[10]+z[14]],this.mm2ortho=create$3(),invert(this.mm2ortho,w)}THD_daxes_to_NIFTI(u,h,g){const v=this.hdr;if(v===null)throw new Error("HDR is not set");v.sform_code=2;const w="xxyyzzg";let C=-1,k=-1,U=-1;const N=["x","y","z"];N[0]=w[g[0]],N[1]=w[g[1]],N[2]=w[g[2]];const O=u.slice(0,3),d=h.slice(0,3);for(let M=0;M<3;M++)N[M]==="x"?C=M:N[M]==="y"?k=M:U=M;C<0||k<0||U<0||C===k||C===U||k===U||(v.pixDims[1]=Math.abs(O[0]),v.pixDims[2]=Math.abs(O[1]),v.pixDims[3]=Math.abs(O[2]),v.affine=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],v.affine[0][C]=-O[C],v.affine[1][k]=-O[k],v.affine[2][U]=O[U],v.affine[0][3]=-d[C],v.affine[1][3]=-d[k],v.affine[2][3]=d[U])}SetPixDimFromSForm(){if(!this.hdr)throw new Error("hdr not defined");const u=this.hdr.affine,h=fromValues$3(u[0][0],u[0][1],u[0][2],u[0][3],u[1][0],u[1][1],u[1][2],u[1][3],u[2][0],u[2][1],u[2][2],u[2][3],u[3][0],u[3][1],u[3][2],u[3][3]),g=this.vox2mm([0,0,0],h),v=this.vox2mm([1,0,0],h);subtract$1(v,v,g);const w=this.vox2mm([0,1,0],h);subtract$1(w,w,g);const C=this.vox2mm([0,0,1],h);subtract$1(C,C,g),this.hdr.pixDims[1]=length$1(v),this.hdr.pixDims[2]=length$1(w),this.hdr.pixDims[3]=length$1(C)}readDICOM(u){if(this.series=new daikon.Series,Array.isArray(u))for(let d=0;d<u.length;d++){const M=new DataView(u[d]),e=daikon.Series.parseImage(M);e===null?log.error(daikon.Series.parserError):e.hasPixelData()&&(this.series.images.length===0||e.getSeriesId()===this.series.images[0].getSeriesId())&&this.series.addImage(e)}else{const d=daikon.Series.parseImage(new DataView(u));d===null?log.error(daikon.Series.parserError):d.hasPixelData()&&(this.series.images.length===0||d.getSeriesId()===this.series.images[0].getSeriesId())&&this.series.addImage(d)}this.series.buildSeries(),this.hdr=new nifti.NIFTI1;const h=this.hdr;h.scl_inter=0,h.scl_slope=1,this.series.images[0].getDataScaleIntercept()&&(h.scl_inter=this.series.images[0].getDataScaleIntercept()),this.series.images[0].getDataScaleSlope()&&(h.scl_slope=this.series.images[0].getDataScaleSlope()),h.dims=[3,1,1,1,0,0,0,0],h.pixDims=[1,1,1,1,1,0,0,0],h.dims[1]=this.series.images[0].getCols(),h.dims[2]=this.series.images[0].getRows(),h.dims[3]=this.series.images[0].getNumberOfFrames(),this.series.images.length>1&&(h.dims[3]>1&&log.debug("To Do: multiple slices per file and multiple files (XA30 DWI)"),h.dims[3]=this.series.images.length);const g=this.series.images[0].getPixelSpacing();if(h.pixDims[1]=g[0],h.pixDims[2]=g[1],this.series.images.length>1){const d=fromValues$2(...this.series.images[0].getImagePosition()),M=fromValues$2(...this.series.images[1].getImagePosition()),e=fromValues$2(0,0,0);subtract$1(e,d,M),h.pixDims[3]=length$1(e)}else h.pixDims[3]=this.series.images[0].getSliceThickness();h.pixDims[4]=this.series.images[0].getTR()/1e3;const v=this.series.images[0].getDataType(),w=this.series.images[0].getBitsAllocated();h.numBitsPerVoxel=w,this.hdr.littleEndian=this.series.images[0].littleEndian,w===8&&v===2?h.datatypeCode=NiiDataType.DT_INT8:w===8&&v===3?h.datatypeCode=NiiDataType.DT_UINT8:w===16&&v===2?h.datatypeCode=NiiDataType.DT_INT16:w===16&&v===3?h.datatypeCode=NiiDataType.DT_UINT16:w===32&&v===2?h.datatypeCode=NiiDataType.DT_INT32:w===32&&v===3?h.datatypeCode=NiiDataType.DT_UINT32:w===32&&v===4?h.datatypeCode=NiiDataType.DT_FLOAT32:w===64&&v===4?h.datatypeCode=NiiDataType.DT_FLOAT64:w===1?h.datatypeCode=NiiDataType.DT_BINARY:log.warn("Unsupported DICOM format: "+v+" "+w);const C=h.pixDims.slice(1,4),k=getBestTransform(this.series.images[0].getImageDirections(),C,this.series.images[0].getImagePosition());k&&(h.sform_code=1,h.affine=[[k[0][0],k[0][1],k[0][2],k[0][3]],[k[1][0],k[1][1],k[1][2],k[1][3]],[k[2][0],k[2][1],k[2][2],k[2][3]],[0,0,0,1]]);let U,N=this.series.validatePixelDataLength(this.series.images[0]);const O=new Uint8Array(new ArrayBuffer(N*this.series.images.length));for(let d=0;d<this.series.images.length;d++)this.series.isMosaic?U=this.series.getMosaicData(this.series.images[d],this.series.images[d].getPixelDataBytes()):U=this.series.images[d].getPixelDataBytes(),N=this.series.validatePixelDataLength(this.series.images[d]),this.series.images[d].clearPixelData(),O.set(new Uint8Array(U,0,N),N*d);return O.buffer}readECAT(u){this.hdr=new nifti.NIFTI1;const h=this.hdr;h.dims=[3,1,1,1,0,0,0,0],h.pixDims=[1,1,1,1,1,0,0,0];const g=new DataView(u),v=g.getInt32(0,!1),w=g.getInt16(50,!1);if(v!==1296127058||w<1||w>14)throw new Error("Not a valid ECAT file");let C=512,k=0;const U=[];let N=new Float32Array;for(;;){const O=g.getInt32(C,!1),d=g.getInt32(C+12,!1);if(O+d!==31)break;let M=C+20,e=0,b=0;for(;e<31&&(b=g.getInt32(M,!1),M+=16,b!==0);){e++;let z=b*512;const W=z-512,s0=g.getUint16(W,!1);h.dims[1]=g.getUint16(W+4,!1),h.dims[2]=g.getUint16(W+6,!1),h.dims[3]=g.getUint16(W+8,!1);const K=g.getFloat32(W+26,!1);h.pixDims[1]=g.getFloat32(W+34,!1)*10,h.pixDims[2]=g.getFloat32(W+38,!1)*10,h.pixDims[3]=g.getFloat32(W+42,!1)*10,h.pixDims[4]=g.getUint32(W+46,!1)/1e3,U.push(h.pixDims[4]);const J=h.dims[1]*h.dims[2]*h.dims[3],D=new Float32Array(J);if(s0===1)for(let X=0;X<J;X++)D[X]=g.getUint8(z)*K,z++;else if(s0===6)for(let X=0;X<J;X++)D[X]=g.getUint16(z,!1)*K,z+=2;else if(s0===7)for(let X=0;X<J;X++)D[X]=g.getUint32(z,!1)*K,z+=4;else log.warn("Unknown ECAT data type "+s0);const Z=N.slice(0);N=new Float32Array(Z.length+D.length),N.set(Z),N.set(D,Z.length),k++}if(b===0)break;C+=512}if(h.dims[4]=k,h.pixDims[4]=U[0],k>1){h.dims[0]=4;let O=!1;for(let d=0;d<k;d++)U[d]!==U[0]&&(O=!0);O&&log.warn("Frame durations vary")}return h.sform_code=1,h.affine=[[-h.pixDims[1],0,0,(h.dims[1]-2)*.5*h.pixDims[1]],[0,-h.pixDims[2],0,(h.dims[2]-2)*.5*h.pixDims[2]],[0,0,-h.pixDims[3],(h.dims[3]-2)*.5*h.pixDims[3]],[0,0,0,1]],h.numBitsPerVoxel=32,h.datatypeCode=NiiDataType.DT_FLOAT32,N}readV16(u){this.hdr=new nifti.NIFTI1;const h=this.hdr;h.dims=[3,1,1,1,0,0,0,0],h.pixDims=[1,1,1,1,1,0,0,0];const g=new DataView(u);return h.dims[1]=g.getUint16(0,!0),h.dims[2]=g.getUint16(2,!0),h.dims[3]=g.getUint16(4,!0),2*h.dims[1]*h.dims[2]*h.dims[3]+6!==u.byteLength&&log.warn("This does not look like a valid BrainVoyager V16 file"),h.numBitsPerVoxel=16,h.datatypeCode=NiiDataType.DT_UINT16,log.warn("Warning: V16 files have no spatial transforms"),h.affine=[[0,0,-h.pixDims[1],(h.dims[1]-2)*.5*h.pixDims[1]],[-h.pixDims[2],0,0,(h.dims[2]-2)*.5*h.pixDims[2]],[0,-h.pixDims[3],0,(h.dims[3]-2)*.5*h.pixDims[3]],[0,0,0,1]],h.littleEndian=!0,u.slice(6)}readVMR(u){this.hdr=new nifti.NIFTI1;const h=this.hdr;h.dims=[3,1,1,1,0,0,0,0],h.pixDims=[1,1,1,1,1,0,0,0];const g=new DataView(u),v=g.getUint16(0,!0);v!==4&&log.warn("Not a valid version 4 VMR image"),h.dims[1]=g.getUint16(2,!0),h.dims[2]=g.getUint16(4,!0),h.dims[3]=g.getUint16(6,!0);const w=h.dims[1]*h.dims[2]*h.dims[3];if(v>=4){let C=8+w;const k=g.getUint32(C+88,!0);if(C=C+92,k>0){const U=u.byteLength;for(let N=0;N<k;N++){for(;C<U&&g.getUint8(C)!==0;)C++;for(C++,C+=4;C<U&&g.getUint8(C)!==0;)C++;C++;const O=g.getUint32(C,!0);C+=4;for(let d=0;d<O;d++)C+=4}}h.pixDims[1]=g.getFloat32(C+2,!0),h.pixDims[2]=g.getFloat32(C+6,!0),h.pixDims[3]=g.getFloat32(C+10,!0)}return log.warn("Warning: VMR spatial transform not implemented"),h.affine=[[0,0,-h.pixDims[1],(h.dims[1]-2)*.5*h.pixDims[1]],[-h.pixDims[2],0,0,(h.dims[2]-2)*.5*h.pixDims[2]],[0,-h.pixDims[3],0,(h.dims[3]-2)*.5*h.pixDims[3]],[0,0,0,1]],log.debug(h),h.numBitsPerVoxel=8,h.datatypeCode=NiiDataType.DT_UINT8,u.slice(8,8+w)}readMGH(u){this.hdr=new nifti.NIFTI1;const h=this.hdr;h.littleEndian=!1,h.dims=[3,1,1,1,0,0,0,0],h.pixDims=[1,1,1,1,1,0,0,0];let g=u,v=new DataView(g);v.getUint8(0)===31&&v.getUint8(1)===139&&(g=decompressSync$1(new Uint8Array(u)).buffer,v=new DataView(g));const w=v.getInt32(0,!1),C=v.getInt32(4,!1),k=v.getInt32(8,!1),U=v.getInt32(12,!1),N=v.getInt32(16,!1),O=v.getInt32(20,!1),d=v.getFloat32(30,!1),M=v.getFloat32(34,!1),e=v.getFloat32(38,!1),b=v.getFloat32(42,!1),z=v.getFloat32(46,!1),W=v.getFloat32(50,!1),s0=v.getFloat32(54,!1),K=v.getFloat32(58,!1),J=v.getFloat32(62,!1),D=v.getFloat32(66,!1),Z=v.getFloat32(70,!1),X=v.getFloat32(74,!1),r0=v.getFloat32(78,!1),l0=v.getFloat32(82,!1),j=v.getFloat32(86,!1);(w!==1||O<0||O>4)&&log.warn("Not a valid MGH file"),O===0?(h.numBitsPerVoxel=8,h.datatypeCode=NiiDataType.DT_UINT8):O===4?(h.numBitsPerVoxel=16,h.datatypeCode=NiiDataType.DT_INT16):O===1?(h.numBitsPerVoxel=32,h.datatypeCode=NiiDataType.DT_INT32):O===3&&(h.numBitsPerVoxel=32,h.datatypeCode=NiiDataType.DT_FLOAT32),h.dims[1]=C,h.dims[2]=k,h.dims[3]=U,h.dims[4]=N,N>1&&(h.dims[0]=4),h.pixDims[1]=d,h.pixDims[2]=M,h.pixDims[3]=e,h.vox_offset=284,h.sform_code=1;const f=fromValues$3(b*h.pixDims[1],s0*h.pixDims[2],D*h.pixDims[3],0,z*h.pixDims[1],K*h.pixDims[2],Z*h.pixDims[3],0,W*h.pixDims[1],J*h.pixDims[2],X*h.pixDims[3],0,0,0,0,1),c0=[h.dims[1]/2,h.dims[2]/2,h.dims[3]/2,1],h0=[0,0,0,0];for(let w0=0;w0<3;w0++){h0[w0]=0;for(let x0=0;x0<3;x0++)h0[w0]=h0[w0]+f[x0+w0*4]*c0[x0]}h.affine=[[f[0],f[1],f[2],r0-h0[0]],[f[4],f[5],f[6],l0-h0[1]],[f[8],f[9],f[10],j-h0[2]],[0,0,0,1]];const A0=h.dims[1]*h.dims[2]*h.dims[3]*h.dims[4]*(h.numBitsPerVoxel/8);return g.slice(h.vox_offset,h.vox_offset+A0)}readHEAD(u,h){this.hdr=new nifti.NIFTI1;const g=this.hdr;g.dims[0]=3,g.pixDims=[1,1,1,1,1,0,0,0];let v=[0,0,0],w=[0,0,0],C=[1,1,1];const U=new TextDecoder().decode(u).split(/\r?\n/),N=(u.byteLength+8)%16,O=u.byteLength+(16-N);log.debug(u.byteLength,"len",O);const d=new Uint8Array(O);d.fill(0),d.set(new Uint8Array(u));const M=new nifti.NIFTIEXTENSION(O+8,42,d,!0);g.addExtension(M),g.extensionCode=42,g.extensionFlag[0]=1,g.extensionSize=O+8;const e=U.length;let b=0,z=!1;for(;b<e;){let s0=U[b];if(b++,!s0.startsWith("type"))continue;const K=s0.includes("integer-attribute"),J=s0.includes("float-attribute");if(s0=U[b],b++,!s0.startsWith("name"))continue;let D=s0.split("= ");const Z=D[1];s0=U[b],b++,D=s0.split("= ");let X=parseInt(D[1]);if(!(X<1)){if(s0=U[b],b++,D=s0.trim().split(/\s+/),J||K){for(;D.length<X;){s0=U[b],b++;const r0=s0.trim().split(/\s+/);D.push(...r0)}for(let r0=0;r0<X;r0++)D[r0]=parseFloat(D[r0])}switch(Z){case"BYTEORDER_STRING":D[0].includes("LSB_FIRST")?g.littleEndian=!0:D[0].includes("MSB_FIRST")&&(g.littleEndian=!1);break;case"BRICK_TYPES":{g.dims[4]=X;const r0=parseInt(D[0]);r0===0?(g.numBitsPerVoxel=8,g.datatypeCode=NiiDataType.DT_UINT8):r0===1?(g.numBitsPerVoxel=16,g.datatypeCode=NiiDataType.DT_INT16):r0===3?(g.numBitsPerVoxel=32,g.datatypeCode=NiiDataType.DT_FLOAT32):log.warn("Unknown BRICK_TYPES ",r0)}break;case"IJK_TO_DICOM_REAL":if(X<12)break;z=!0,g.sform_code=2,g.affine=[[-D[0],-D[1],-D[2],-D[3]],[-D[4],-D[5],-D[6],-D[7]],[D[8],D[9],D[10],D[11]],[0,0,0,1]];break;case"DATASET_DIMENSIONS":X=Math.max(X,3);for(let r0=0;r0<X;r0++)g.dims[r0+1]=D[r0];break;case"ORIENT_SPECIFIC":v=D;break;case"ORIGIN":w=D;break;case"DELTA":C=D;break;case"TAXIS_FLOATS":g.pixDims[4]=D[0];break;default:log.warn("Unknown:",Z)}}}z?this.SetPixDimFromSForm():this.THD_daxes_to_NIFTI(C,w,v);const W=g.numBitsPerVoxel/8*g.dims[1]*g.dims[2]*g.dims[3]*g.dims[4];if(!h)throw new Error("pairedImgData not set");return h.byteLength<W?decompressSync$1(new Uint8Array(h)).buffer:h.slice(0)}readMHA(u,h){const g=u.byteLength;if(g<20)throw new Error("File too small to be VTK: bytes = "+u.byteLength);const v=new Uint8Array(u);let w=0;function C(z){return z===10||z===13}function k(){for(;w<g&&C(v[w]);)w++;const z=w;for(;w<g&&!C(v[w]);)w++;return w-z<2?"":new TextDecoder().decode(u.slice(z,w))}let U=k();this.hdr=new nifti.NIFTI1;const N=this.hdr;N.pixDims=[1,1,1,1,1,0,0,0],N.dims=[1,1,1,1,1,1,1,1],N.littleEndian=!0;let O=!1,d=!1;const M=fromValues$4(NaN,0,0,0,1,0,0,0,1),e=fromValues$2(0,0,0);for(;U!=="";){let z=U.split(" ");if(z.length>2&&(z=z.slice(2)),U.startsWith("BinaryDataByteOrderMSB")&&z[0].includes("False")&&(N.littleEndian=!0),U.startsWith("BinaryDataByteOrderMSB")&&z[0].includes("True")&&(N.littleEndian=!1),U.startsWith("CompressedData")&&z[0].includes("True")&&(O=!0),U.startsWith("TransformMatrix"))for(let W=0;W<9;W++)M[W]=parseFloat(z[W]);if(U.startsWith("Offset"))for(let W=0;W<Math.min(z.length,3);W++)e[W]=parseFloat(z[W]);if(U.startsWith("ElementSpacing"))for(let W=0;W<z.length;W++)N.pixDims[W+1]=parseFloat(z[W]);if(U.startsWith("DimSize")){N.dims[0]=z.length;for(let W=0;W<z.length;W++)N.dims[W+1]=parseInt(z[W])}if(U.startsWith("ElementType"))switch(z[0]){case"MET_UCHAR":N.numBitsPerVoxel=8,N.datatypeCode=NiiDataType.DT_UINT8;break;case"MET_CHAR":N.numBitsPerVoxel=8,N.datatypeCode=NiiDataType.DT_INT8;break;case"MET_SHORT":N.numBitsPerVoxel=16,N.datatypeCode=NiiDataType.DT_INT16;break;case"MET_USHORT":N.numBitsPerVoxel=16,N.datatypeCode=NiiDataType.DT_UINT16;break;case"MET_INT":N.numBitsPerVoxel=32,N.datatypeCode=NiiDataType.DT_INT32;break;case"MET_UINT":N.numBitsPerVoxel=32,N.datatypeCode=NiiDataType.DT_UINT32;break;case"MET_FLOAT":N.numBitsPerVoxel=32,N.datatypeCode=NiiDataType.DT_FLOAT32;break;case"MET_DOUBLE":N.numBitsPerVoxel=64,N.datatypeCode=NiiDataType.DT_FLOAT64;break;default:throw new Error("Unsupported NRRD data type: "+z[0])}if(U.startsWith("ObjectType")&&!z[0].includes("Image")&&log.warn("Only able to read ObjectType = Image, not "+U),U.startsWith("ElementDataFile")){z[0]!=="LOCAL"&&(d=!0);break}U=k()}const b=fromValues$4(N.pixDims[1],0,0,0,N.pixDims[2],0,0,0,N.pixDims[3]);return multiply$1(M,M,b),N.affine=[[-M[0],-M[3],-M[6],-e[0]],[-M[1],-M[4],-M[7],-e[1]],[M[2],M[5],M[8],e[2]],[0,0,0,1]],N.vox_offset=w,d&&h?O?decompressSync$1(new Uint8Array(h.slice(0))).buffer:h.slice(0):O?decompressSync$1(new Uint8Array(u.slice(N.vox_offset))).buffer:u.slice(N.vox_offset)}readMIF(u,h){this.hdr=new nifti.NIFTI1;const g=this.hdr;g.pixDims=[1,1,1,1,1,0,0,0],g.dims=[1,1,1,1,1,1,1,1];let v=u.byteLength;if(v<20)throw new Error("File too small to be MIF: bytes = "+v);const w=new Uint8Array(u);w[0]===31&&w[1]===139&&(log.debug("MIF with GZ decompression"),u=decompressSync$1(new Uint8Array(u)).buffer,v=u.byteLength);let C=0;function k(){for(;C<v&&w[C]===10;)C++;const c0=C;for(;C<v&&w[C]!==10;)C++;return C++,C-c0<1?"":new TextDecoder().decode(u.slice(c0,C-1))}let U=k();if(!U.startsWith("mrtrix image"))throw new Error("Not a valid MIF file");const N=[];let O=0,d=0,M=!1;for(U=k();C<v&&!U.startsWith("END");){let c0=U.split(":");if(U=k(),c0.length<2)break;const h0=c0[0];c0=c0[1].split(",");for(let A0=0;A0<c0.length;A0++)c0[A0]=c0[A0].trim();switch(h0){case"dim":g.dims[0]=c0.length;for(let A0=0;A0<c0.length;A0++)g.dims[A0+1]=parseInt(c0[A0]);break;case"vox":for(let A0=0;A0<c0.length;A0++)g.pixDims[A0+1]=parseFloat(c0[A0]),isNaN(g.pixDims[A0+1])&&(g.pixDims[A0+1]=0);break;case"layout":for(let A0=0;A0<c0.length;A0++)N.push(parseInt(c0[A0]));break;case"datatype":{const A0=c0[0];A0.startsWith("Int8")?g.datatypeCode=NiiDataType.DT_INT8:A0.startsWith("UInt8")?g.datatypeCode=NiiDataType.DT_UINT8:A0.startsWith("Int16")?g.datatypeCode=NiiDataType.DT_INT16:A0.startsWith("UInt16")?g.datatypeCode=NiiDataType.DT_UINT16:A0.startsWith("Int32")?g.datatypeCode=NiiDataType.DT_INT32:A0.startsWith("UInt32")?g.datatypeCode=NiiDataType.DT_UINT32:A0.startsWith("Float32")?g.datatypeCode=NiiDataType.DT_FLOAT32:A0.startsWith("Float64")?g.datatypeCode=NiiDataType.DT_FLOAT64:log.warn("Unsupported datatype "+A0),A0.includes("8")?g.numBitsPerVoxel=8:A0.includes("16")?g.numBitsPerVoxel=16:A0.includes("32")?g.numBitsPerVoxel=32:A0.includes("64")&&(g.numBitsPerVoxel=64),g.littleEndian=!0,A0.endsWith("LE")&&(g.littleEndian=!0),A0.endsWith("BE")&&(g.littleEndian=!1)}break;case"transform":if(O>2||c0.length!==4)break;g.affine[O][0]=parseFloat(c0[0]),g.affine[O][1]=parseFloat(c0[1]),g.affine[O][2]=parseFloat(c0[2]),g.affine[O][3]=parseFloat(c0[3]),O++;break;case"RepetitionTime":d=parseFloat(c0[0]);break;case"file":M=!c0[0].startsWith(". "),M||(c0=c0[0].split(" "),g.vox_offset=parseInt(c0[1]));break}}const e=g.dims[0];e>5&&log.warn("reader only designed for a maximum of 5 dimensions (XYZTD)");let b=1;for(let c0=0;c0<e;c0++)b*=Math.max(g.dims[c0+1],1);log.debug(b);for(let c0=0;c0<3;c0++)for(let h0=0;h0<3;h0++)g.affine[c0][h0]*=g.pixDims[h0+1];log.debug("mif affine:"+g.affine[0]),d>0&&(g.pixDims[4]=d),M&&!h&&log.warn("MIH header provided without paired image data");let z;h&&M?z=h.slice(0):z=u.slice(g.vox_offset,g.vox_offset+b*(g.numBitsPerVoxel/8)),N.length!==g.dims[0]&&log.warn("dims does not match layout");let W=1;const s0=[1,1,1,1,1],K=[!1,!1,!1,!1,!1];for(let c0=0;c0<N.length;c0++)for(let h0=0;h0<N.length;h0++)Math.abs(N[h0])===c0&&(s0[h0]=W,(N[h0]<0||Object.is(N[h0],-0))&&(K[h0]=!0),W*=g.dims[h0+1]);let J=NVUtilities.range(0,g.dims[1]-1,1);K[0]&&(J=NVUtilities.range(g.dims[1]-1,0,-1));for(let c0=0;c0<g.dims[1];c0++)J[c0]*=s0[0];let D=NVUtilities.range(0,g.dims[2]-1,1);K[1]&&(D=NVUtilities.range(g.dims[2]-1,0,-1));for(let c0=0;c0<g.dims[2];c0++)D[c0]*=s0[1];let Z=NVUtilities.range(0,g.dims[3]-1,1);K[2]&&(Z=NVUtilities.range(g.dims[3]-1,0,-1));for(let c0=0;c0<g.dims[3];c0++)Z[c0]*=s0[2];let X=NVUtilities.range(0,g.dims[4]-1,1);K[3]&&(X=NVUtilities.range(g.dims[4]-1,0,-1));for(let c0=0;c0<g.dims[4];c0++)X[c0]*=s0[3];let r0=NVUtilities.range(0,g.dims[5]-1,1);K[4]&&(r0=NVUtilities.range(g.dims[5]-1,0,-1));for(let c0=0;c0<g.dims[5];c0++)r0[c0]*=s0[4];let l0=0,j,f;switch(g.numBitsPerVoxel){case 8:j=new Uint8Array(z),f=new Uint8Array(b);break;case 16:j=new Uint16Array(z),f=new Uint16Array(b);break;case 32:j=new Uint32Array(z),f=new Uint32Array(b);break;case 64:j=new BigUint64Array(z),f=new BigUint64Array(b);break;default:throw new Error("unknown numBitsPerVoxel")}for(let c0=0;c0<g.dims[5];c0++)for(let h0=0;h0<g.dims[4];h0++)for(let A0=0;A0<g.dims[3];A0++)for(let w0=0;w0<g.dims[2];w0++)for(let x0=0;x0<g.dims[1];x0++)f[l0]=j[J[x0]+D[w0]+Z[A0]+X[h0]+r0[c0]],l0++;return f}readNRRD(u,h){this.hdr=new nifti.NIFTI1;const g=this.hdr;g.pixDims=[1,1,1,1,1,0,0,0];const v=u.byteLength;let w=null;const C=new Uint8Array(u);for(let z=1;z<v;z++)if(C[z-1]===10&&C[z]===10){const W=u.slice(0,z-1);w=new TextDecoder().decode(W),g.vox_offset=z+1;break}if(w===null)throw new Error("could not extract txt");const k=w.split(`
1613
1613
  `);k[0].startsWith("NRRD")||alert("Invalid NRRD image");const U=k.length;let N=!1,O=!1,d=!1;const M=fromValues$4(NaN,0,0,0,1,0,0,0,1),e=fromValues$2(0,0,0);let b=create$4();for(let z=1;z<U;z++){let W=k[z];if(W[0]==="#")continue;W=W.toLowerCase();const s0=W.split(":");if(s0.length<2)continue;const K=s0[0].trim();let J=s0[1].trim();switch(J=J.replaceAll(")"," "),J=J.replaceAll("("," "),J=J.trim(),K){case"data file":d=!0;break;case"encoding":J.includes("raw")?N=!1:J.includes("gz")?N=!0:alert("Unsupported NRRD encoding");break;case"type":switch(J){case"uchar":case"unsigned char":case"uint8":case"uint8_t":g.numBitsPerVoxel=8,g.datatypeCode=NiiDataType.DT_UINT8;break;case"signed char":case"int8":case"int8_t":g.numBitsPerVoxel=8,g.datatypeCode=NiiDataType.DT_INT8;break;case"short":case"short int":case"signed short":case"signed short int":case"int16":case"int16_t":g.numBitsPerVoxel=16,g.datatypeCode=NiiDataType.DT_INT16;break;case"ushort":case"unsigned short":case"unsigned short int":case"uint16":case"uint16_t":g.numBitsPerVoxel=16,g.datatypeCode=NiiDataType.DT_UINT16;break;case"int":case"signed int":case"int32":case"int32_t":g.numBitsPerVoxel=32,g.datatypeCode=NiiDataType.DT_INT32;break;case"uint":case"unsigned int":case"uint32":case"uint32_t":g.numBitsPerVoxel=32,g.datatypeCode=NiiDataType.DT_UINT32;break;case"float":g.numBitsPerVoxel=32,g.datatypeCode=NiiDataType.DT_FLOAT32;break;case"double":g.numBitsPerVoxel=64,g.datatypeCode=NiiDataType.DT_FLOAT64;break;default:throw new Error("Unsupported NRRD data type: "+J)}break;case"spacings":{const D=J.split(/[ ,]+/);for(let Z=0;Z<D.length;Z++)g.pixDims[Z+1]=parseFloat(D[Z])}break;case"sizes":{const D=J.split(/[ ,]+/);g.dims[0]=D.length;for(let Z=0;Z<D.length;Z++)g.dims[Z+1]=parseInt(D[Z])}break;case"endian":J.includes("little")?g.littleEndian=!0:J.includes("big")&&(g.littleEndian=!1);break;case"space directions":{const D=J.split(/[ ,]+/);if(D.length!==9)break;for(let Z=0;Z<9;Z++)M[Z]=parseFloat(D[Z])}break;case"space origin":{const D=J.split(/[ ,]+/);if(D.length!==3)break;e[0]=parseFloat(D[0]),e[1]=parseFloat(D[1]),e[2]=parseFloat(D[2])}break;case"space units":J.includes("microns")&&(O=!0);break;case"space":J.includes("right-anterior-superior")||J.includes("RAS")?b=fromValues$4(1,0,0,0,1,0,0,0,1):J.includes("left-anterior-superior")||J.includes("LAS")?b=fromValues$4(-1,0,0,0,1,0,0,0,1):J.includes("left-posterior-superior")||J.includes("LPS")?b=fromValues$4(-1,0,0,0,-1,0,0,0,1):log.warn("Unsupported NRRD space value:",J);break;default:log.warn("Unknown:",K)}}if(!isNaN(M[0])){this.hdr.sform_code=2,O&&(multiplyScalar(M,M,.001),e[0]*=.001,e[1]*=.001,e[2]*=.001),b[0]<0&&(e[0]=-e[0]),b[4]<0&&(e[1]=-e[1]),b[8]<0&&(e[2]=-e[2]),multiply$1(M,b,M);const z=fromValues$3(M[0],M[3],M[6],e[0],M[1],M[4],M[7],e[1],M[2],M[5],M[8],e[2],0,0,0,1),W=this.vox2mm([0,0,0],z),s0=this.vox2mm([1,0,0],z);subtract$1(s0,s0,W);const K=this.vox2mm([0,1,0],z);subtract$1(K,K,W);const J=this.vox2mm([0,0,1],z);subtract$1(J,J,W),g.pixDims[1]=length$1(s0),g.pixDims[2]=length$1(K),g.pixDims[3]=length$1(J),g.affine=[[z[0],z[1],z[2],z[3]],[z[4],z[5],z[6],z[7]],[z[8],z[9],z[10],z[11]],[0,0,0,1]]}return d&&h?h.slice(0):(d&&log.warn("Missing data: NRRD header describes detached data file but only one URL provided"),N?decompressSync$1(new Uint8Array(u.slice(g.vox_offset))).buffer:u.slice(g.vox_offset))}calculateRAS(){if(!this.hdr)throw new Error("hdr not set");const u=this.hdr.affine,h=this.hdr,g=fromValues$4(Math.abs(u[0][0]),Math.abs(u[0][1]),Math.abs(u[0][2]),Math.abs(u[1][0]),Math.abs(u[1][1]),Math.abs(u[1][2]),Math.abs(u[2][0]),Math.abs(u[2][1]),Math.abs(u[2][2])),v=[1,1,1];g[3]>g[0]&&(v[0]=2),g[6]>g[0]&&g[6]>g[3]&&(v[0]=3),v[1]=1,v[0]===1?g[4]>g[7]?v[1]=2:v[1]=3:v[0]===2?g[1]>g[7]?v[1]=1:v[1]=3:g[1]>g[4]?v[1]=1:v[1]=2,v[2]=6-v[1]-v[0];let w=[1,2,3];w[v[0]-1]=1,w[v[1]-1]=2,w[v[2]-1]=3;let C=fromValues$3(u[0][0],u[0][1],u[0][2],u[0][3],u[1][0],u[1][1],u[1][2],u[1][3],u[2][0],u[2][1],u[2][2],u[2][3],0,0,0,1);this.mm000=this.vox2mm([-.5,-.5,-.5],C),this.mm100=this.vox2mm([h.dims[1]-.5,-.5,-.5],C),this.mm010=this.vox2mm([-.5,h.dims[2]-.5,-.5],C),this.mm001=this.vox2mm([-.5,-.5,h.dims[3]-.5],C);const k=create$3();copy$1(k,C);for(let W=0;W<3;W++)for(let s0=0;s0<3;s0++)k[W*4+s0]=C[W*4+w[s0]-1];const U=[0,0,0];k[0]<0&&(U[0]=1),k[5]<0&&(U[1]=1),k[10]<0&&(U[2]=1),this.dimsRAS=[h.dims[0],h.dims[w[0]],h.dims[w[1]],h.dims[w[2]]],this.pixDimsRAS=[h.pixDims[0],h.pixDims[w[0]],h.pixDims[w[1]],h.pixDims[w[2]]],this.permRAS=w.slice();for(let W=0;W<3;W++)U[W]===1&&(this.permRAS[W]=-this.permRAS[W]);if(this.arrayEquals(w,[1,2,3])&&this.arrayEquals(U,[0,0,0])){this.toRAS=create$3(),this.matRAS=clone$2(C),this.calculateOblique(),this.img2RASstep=[1,this.dimsRAS[1],this.dimsRAS[1]*this.dimsRAS[2]],this.img2RASstart=[0,0,0];return}identity$1(C),C[0+0*4]=1-U[0]*2,C[1+1*4]=1-U[1]*2,C[2+2*4]=1-U[2]*2,C[3+0*4]=(h.dims[w[0]]-1)*U[0],C[3+1*4]=(h.dims[w[1]]-1)*U[1],C[3+2*4]=(h.dims[w[2]]-1)*U[2];const N=create$3();invert(N,C),multiply(N,N,k),this.matRAS=clone$2(N),C=fromValues$3(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),C[w[0]-1+0*4]=-U[0]*2+1,C[w[1]-1+1*4]=-U[1]*2+1,C[w[2]-1+2*4]=-U[2]*2+1,C[3+0*4]=U[0],C[3+1*4]=U[1],C[3+2*4]=U[2],this.toRAS=clone$2(C),C[3]=0,C[7]=0,C[11]=0,C[12]=0,(this.permRAS[0]===-1||this.permRAS[1]===-1||this.permRAS[2]===-1)&&(C[12]=h.dims[1]-1),C[13]=0,(this.permRAS[0]===-2||this.permRAS[1]===-2||this.permRAS[2]===-2)&&(C[13]=h.dims[2]-1),C[14]=0,(this.permRAS[0]===-3||this.permRAS[1]===-3||this.permRAS[2]===-3)&&(C[14]=h.dims[3]-1),this.toRASvox=clone$2(C),log.debug(this.hdr.dims),log.debug(this.dimsRAS);const O=this.hdr;w=this.permRAS;const d=[Math.abs(w[0]),Math.abs(w[1]),Math.abs(w[2])],M=[O.dims[d[0]],O.dims[d[1]],O.dims[d[2]]],e=[1,O.dims[1],O.dims[1]*O.dims[2]],b=[e[d[0]-1],e[d[1]-1],e[d[2]-1]],z=[0,0,0];for(let W=0;W<3;W++)w[W]<0&&(z[W]=b[W]*(M[W]-1),b[W]=-b[W]);this.img2RASstep=b,this.img2RASstart=z,this.calculateOblique()}img2RAS(){if(!this.permRAS)throw new Error("permRAS undefined");if(!this.img)throw new Error("img undefined");if(!this.hdr)throw new Error("hdr undefined");const u=this.permRAS.slice();if(u[0]===1&&u[1]===2&&u[2]===3)return this.img;const h=this.hdr,g=this.img.slice(0,h.dims[1]*h.dims[1]*h.dims[2]*h.dims[3]),v=[Math.abs(u[0]),Math.abs(u[1]),Math.abs(u[2])],w=[h.dims[v[0]],h.dims[v[1]],h.dims[v[2]]],C=[1,h.dims[1],h.dims[1]*h.dims[2]],k=[C[v[0]-1],C[v[1]-1],C[v[2]-1]],U=[0,0,0];for(let O=0;O<3;O++)u[O]<0&&(U[O]=k[O]*(w[O]-1),k[O]=-k[O]);let N=0;for(let O=0;O<w[2];O++){const d=U[2]+O*k[2];for(let M=0;M<w[1];M++){const e=U[1]+M*k[1];for(let b=0;b<w[0];b++){const z=U[0]+b*k[0];g[N]=this.img[z+e+d],N++}}}return g}vox2mm(u,h){const g=clone$2(h);transpose(g,g);const v=fromValues$1(u[0],u[1],u[2],1);return transformMat4(v,v,g),fromValues$2(v[0],v[1],v[2])}mm2vox(u,h=!1){if(!this.matRAS)throw new Error("matRAS undefined");const g=clone$2(this.matRAS),v=clone$2(g);transpose(v,g),invert(v,v);const w=fromValues$1(u[0],u[1],u[2],1);transformMat4(w,w,v);const C=fromValues$2(w[0],w[1],w[2]);return h?C:[Math.round(C[0]),Math.round(C[1]),Math.round(C[2])]}arrayEquals(u,h){return Array.isArray(u)&&Array.isArray(h)&&u.length===h.length&&u.every((g,v)=>g===h[v])}setColormap(u){this._colormap=u,this.calMinMax(),this.onColormapChange&&this.onColormapChange(this)}setColormapLabel(u){this.colormapLabel=cmapper.makeLabelLut(u)}async setColormapLabelFromUrl(u){this.colormapLabel=await cmapper.makeLabelLutFromUrl(u)}get colormap(){return this._colormap}get colorMap(){return this._colormap}set colormap(u){this.setColormap(u)}set colorMap(u){this.setColormap(u)}get opacity(){return this._opacity}set opacity(u){this._opacity=u,this.onOpacityChange&&this.onOpacityChange(this)}calMinMax(){if(!this.hdr)throw new Error("hdr undefined");if(!this.img)throw new Error("img undefined");let u=Number.POSITIVE_INFINITY,h=Number.NEGATIVE_INFINITY,g=0,v=0;const w=this.img.length,C=this.img.constructor!==Float64Array&&this.img.constructor!==Float32Array&&this.ignoreZeroVoxels;if(C)for(let r0=0;r0<w;r0++)u=Math.min(this.img[r0],u),h=Math.max(this.img[r0],h),this.img[r0]===0&&g++;else for(let r0=0;r0<w;r0++){if(isNaN(this.img[r0])){v++;continue}this.img[r0]===0&&(g++,this.ignoreZeroVoxels)||(u=Math.min(this.img[r0],u),h=Math.max(this.img[r0],h))}const k=this.intensityRaw2Scaled(u),U=this.intensityRaw2Scaled(h),N=cmapper.colormapFromKey(this._colormap);let O=0,d=0;if(N.min!==void 0&&(O=N.min),N.max!==void 0&&(d=N.max),O===d&&this.trustCalMinMax&&isFinite(this.hdr.cal_min)&&isFinite(this.hdr.cal_max)&&this.hdr.cal_max>this.hdr.cal_min)return this.cal_min=this.hdr.cal_min,this.cal_max=this.hdr.cal_max,this.robust_min=this.cal_min,this.robust_max=this.cal_max,this.global_min=k,this.global_max=U,[this.hdr.cal_min,this.hdr.cal_max,this.hdr.cal_min,this.hdr.cal_max];if(O!==d)return this.cal_min=O,this.cal_max=d,this.robust_min=this.cal_min,this.robust_max=this.cal_max,[O,d,O,d];const M=100*g/w;let e=!1;M>60&&!this.ignoreZeroVoxels&&(log.warn(`${Math.round(M)}% of voxels are zero: ignoring zeros for cal_max`),e=!0,this.ignoreZeroVoxels=!0),this.ignoreZeroVoxels||(g=0),g+=v;const b=Math.round((w-g)*this.percentileFrac);if(b<1||u===h)return log.debug("no variability in image intensity?"),this.cal_min=k,this.cal_max=U,this.robust_min=this.cal_min,this.robust_max=this.cal_max,this.global_min=k,this.global_max=U,[k,U,k,U];const z=1001,W=(z-1)/(h-u),s0=new Array(z);for(let r0=0;r0<z;r0++)s0[r0]=0;if(C)for(let r0=0;r0<w;r0++)s0[Math.round((this.img[r0]-u)*W)]++;else if(this.ignoreZeroVoxels)for(let r0=0;r0<w;r0++)this.img[r0]!==0&&(isNaN(this.img[r0])||s0[Math.round((this.img[r0]-u)*W)]++);else for(let r0=0;r0<w;r0++)isNaN(this.img[r0])||s0[Math.round((this.img[r0]-u)*W)]++;let K=0,J=0;for(;K<b;)K+=s0[J],J++;J--,K=0;let D=z;for(;K<b;)D--,K+=s0[D];if(J===D){let r0=-1;for(;r0!==0;)J>0&&(J--,s0[J]>0&&(r0=0)),r0!==0&&D<z-1&&(D++,s0[D]>0&&(r0=0)),J===0&&D===z-1&&(r0=0)}let Z=this.intensityRaw2Scaled(J/W+u),X=this.intensityRaw2Scaled(D/W+u);return this.hdr.cal_min<this.hdr.cal_max&&this.hdr.cal_min>=k&&this.hdr.cal_max<=U&&(Z=this.hdr.cal_min,X=this.hdr.cal_max),e&&(Z=Math.min(Z,0)),this.cal_min=Z,this.cal_max=X,this.robust_min=this.cal_min,this.robust_max=this.cal_max,this.global_min=k,this.global_max=U,[Z,X,k,U]}intensityRaw2Scaled(u){if(!this.hdr)throw new Error("hdr undefined");return this.hdr.scl_slope===0&&(this.hdr.scl_slope=1),u*this.hdr.scl_slope+this.hdr.scl_inter}intensityScaled2Raw(u){if(!this.hdr)throw new Error("hdr undefined");return this.hdr.scl_slope===0&&(this.hdr.scl_slope=1),(u-this.hdr.scl_inter)/this.hdr.scl_slope}saveToUint8Array(u,h=null){if(!this.hdr)throw new Error("hdr undefined");if(!this.img)throw new Error("img undefined");const g=h!==null,v=hdrToArrayBuffer(this.hdr,g),w=new Uint8Array(4);let C=new Uint8Array(this.img.buffer);g&&(C=new Uint8Array(h.buffer));const k=new Uint8Array(v.length+w.length+C.length);k.set(v),k.set(w,v.length),k.set(C,v.length+w.length);let U=null;return u.endsWith(".gz")?U=gzipSync$1(k,{filename:u,mtime:Date.now(),level:6}):U=k,U}saveToDisk(u="",h=null){const g=this.saveToUint8Array(u,h);if(u==="")return log.debug("saveToDisk: empty file name, returning data as Uint8Array rather than triggering download"),g;const v=new Blob([g.buffer],{type:"application/octet-stream"}),w=URL.createObjectURL(v),C=document.createElement("a");return C.setAttribute("href",w),C.setAttribute("download",u),C.style.visibility="hidden",document.body.appendChild(C),C.click(),document.body.removeChild(C),g}static async fetchDicomData(u,h={}){if(u==="")throw Error("url must not be empty");let v=/^(?:[a-z+]+:)?\/\//i.test(u)?u:new URL(u,window.location.href);/(?:.([^.]+))?$/.exec(v.pathname)||(v=new URL("niivue-manifest.txt",u));let k=await fetch(v,{headers:h});if(!k.ok)throw Error(k.statusText);const N=(await k.text()).split(`
1614
- `),d=/(.*\/).*/.exec(v)[0],M=[];for(const e of N){const b=new URL(e,d);if(k=await fetch(b,{headers:h}),!k.ok)throw Error(k.statusText);const z=await k.arrayBuffer();M.push(z)}return M}static async fetchPartial(u,h,g={}){try{return await fetch(u,{headers:{range:`bytes=0-'${h}`,stream:"true",...g}})}catch(v){return log.error(v),log.error("fetchPartial failed, trying again without range header"),await fetch(u,{headers:g})}}static async loadFromUrl({url:u="",urlImgData:h="",headers:g={},name:v="",colormap:w="gray",opacity:C=1,cal_min:k=NaN,cal_max:U=NaN,trustCalMinMax:N=!0,percentileFrac:O=.02,ignoreZeroVoxels:d=!1,useQFormNotSForm:M=!1,colormapNegative:e="",frame4D:b=0,isManifest:z=!1,limitFrames4D:W=NaN,imageType:s0=NVIMAGE_TYPE.UNKNOWN,colorbarVisible:K=!0,buffer:J=new ArrayBuffer(0)}={}){if(u==="")throw Error("url must not be empty");let D=null,Z=null;if(u instanceof Uint8Array&&(u=u.buffer),J.byteLength>0&&(u=J),u instanceof ArrayBuffer)if(Z=u,v!=="")u=v;else{u="array.nii";const f=new Uint8Array(Z);f[0]===31&&f[1]===139&&(u="array.nii.gz")}if(!isNaN(W)){let f=await this.fetchPartial(u,512,g);Z=await f.arrayBuffer();let c0=new Uint8Array(Z),h0=!1;c0[0]===31&&c0[1]===139&&(h0=!0,new Decompress$1(x0=>{c0=x0}).push(c0),Z=c0.buffer);let A0=c0[0]===92&&c0[1]===1;if(A0||(A0=c0[1]===92&&c0[0]===1),!A0)Z=null;else{const w0=nifti.readHeader(Z);if(w0===null)throw new Error("could not read nifti header");const x0=w0.numBitsPerVoxel/8;let C0=1;for(let oe=1;oe<4;oe++)w0.dims[oe]>1&&(C0*=w0.dims[oe]);let E0=1;for(let oe=4;oe<7;oe++)w0.dims[oe]>1&&(E0*=w0.dims[oe]);const M0=Math.max(Math.min(W,E0),1),N0=w0.vox_offset+M0*C0*x0;if(Z.byteLength<N0&&(f=await this.fetchPartial(u,N0,g),Z=await f.arrayBuffer(),h0)){let oe=new Uint8Array(Z);new Decompress$1(Le=>{oe=Le}).push(oe),Z=oe.buffer}Z.byteLength<N0?Z=null:Z=Z.slice(0,N0)}}if(!Z)if(z)Z=await NVImage.fetchDicomData(u,g),s0=NVIMAGE_TYPE.DCM_MANIFEST;else{const f=await fetch(u,{headers:g});if(!f.ok)throw Error(f.statusText);Z=await f.arrayBuffer()}const X=/(?:\.([^.]+))?$/;let r0="";v===""?r0=X.exec(u)[1]:r0=X.exec(v)[1],r0.toUpperCase()==="HEAD"&&h===""&&(h=u.substring(0,u.lastIndexOf("HEAD"))+"BRIK");let l0;if(v===""){try{l0=new URL(u).pathname.split("/")}catch{l0=u.split("/")}v=l0.slice(-1)[0],v.indexOf("?")>-1&&(v=v.slice(0,v.indexOf("?")))}let j=null;if(h.length>0){let f=await fetch(h,{headers:g});f.status===404&&h.lastIndexOf("BRIK")!==-1&&(f=await fetch(h+".gz",{headers:g})),j=await f.arrayBuffer()}if(!Z)throw new Error("Unable to load buffer properly from volume");return D=new NVImage(Z,v,w,C,j,k,U,N,O,d,M,e,b,s0),D.url=u,D.colorbarVisible=K,D}static readFileAsync(u,h=NaN){return new Promise((g,v)=>{const w=new FileReader;w.onload=()=>{u.name.lastIndexOf("gz")!==-1&&isNaN(h)?g(nifti.decompress(w.result)):g(w.result)},w.onerror=v,isNaN(h)?w.readAsArrayBuffer(u):w.readAsArrayBuffer(u.slice(0,h))})}static async loadFromFile({file:u,name:h="",colormap:g="gray",opacity:v=1,urlImgData:w=null,cal_min:C=NaN,cal_max:k=NaN,trustCalMinMax:U=!0,percentileFrac:N=.02,ignoreZeroVoxels:O=!1,useQFormNotSForm:d=!1,colormapNegative:M="",frame4D:e=0,limitFrames4D:b=NaN,imageType:z=NVIMAGE_TYPE.UNKNOWN}){let W=null,s0=[];try{if(Array.isArray(u))for(let J=0;J<u.length;J++)s0.push(await this.readFileAsync(u[J]));else{if(isNaN(b))s0=await this.readFileAsync(u,b);else{s0=await this.readFileAsync(u,512);let J=new Uint8Array(s0),D=!1;J[0]===31&&J[1]===139&&(D=!0,new Decompress$1(r0=>{J=r0}).push(J),s0=J.buffer);let Z=J[0]===92&&J[1]===1;if(Z||(Z=J[1]===92&&J[0]===1),!Z)s0=await this.readFileAsync(u);else{const X=nifti.readHeader(s0);if(!X)throw new Error("could not read nifti header");const r0=X.numBitsPerVoxel/8;let l0=1;for(let h0=1;h0<4;h0++)X.dims[h0]>1&&(l0*=X.dims[h0]);let j=1;for(let h0=4;h0<7;h0++)X.dims[h0]>1&&(j*=X.dims[h0]);const f=Math.max(Math.min(b,j),1),c0=X.vox_offset+f*l0*r0;if(s0.byteLength<c0&&(s0=await this.readFileAsync(u,c0),D)){let h0=new Uint8Array(s0);new Decompress$1(w0=>{h0=w0}).push(h0),s0=h0.buffer}if(s0.byteLength<c0)throw new Error("failed to load image data (e.g. incompressible data)");s0=s0.slice(0,c0)}}h=u.name}let K=null;w&&(K=await this.readFileAsync(w)),W=new NVImage(s0,h,g,v,K,C,k,U,N,O,d,M,e,z),W.fileObject=u}catch(K){log.error(K),log.error(K)}if(W===null)throw new Error("could not build NVImage");return W}static createNiftiArray(u=[256,256,256],h=[1,1,1],g=[1,0,0,-128,0,1,0,-128,0,0,1,-128,0,0,0,1],v=2,w=new Uint8Array){const C=this.createNiftiHeader(u,h,g,v),k=hdrToArrayBuffer(C,!1);if(w.length<1)return k;const U=new Uint8Array(4),N=new Uint8Array(w.buffer),O=new Uint8Array(k.length+U.length+N.length);return O.set(k),O.set(U,k.length),O.set(N,k.length+U.length),O}static createNiftiHeader(u=[256,256,256],h=[1,1,1],g=[1,0,0,-128,0,1,0,-128,0,0,1,-128,0,0,0,1],v=2){const w=new nifti.NIFTI1;w.littleEndian=!0,w.dims=[3,1,1,1,0,0,0,0],w.dims[0]=Math.max(3,u.length);for(let k=0;k<u.length;k++)w.dims[k+1]=u[k];w.pixDims=[1,1,1,1,1,0,0,0];for(let k=0;k<u.length;k++)w.pixDims[k+1]=h[k];if(g.length===16){let k=0;for(let U=0;U<4;U++)for(let N=0;N<4;N++)w.affine[U][N]=g[k],k++}let C=8;return v===256||v===2?C=8:v===512||v===4?C=16:v===16||v===768||v===8?C=32:v===64?C=64:log.warn("Unsupported NIfTI datatypeCode: "+v),w.datatypeCode=v,w.numBitsPerVoxel=C,w.scl_inter=0,w.scl_slope=0,w.sform_code=2,w.magic="n+1",w.vox_offset=352,w}getVolumeData(u=[-1,0,0],h=[0,0,0],g="same"){let v=new Uint8Array;if(Math.min(...u)<0||Math.min(...h)<0)return[v,[0,0,0]];const w=this.dimsRAS.slice(1,4);for(let M=0;M<3;M++)if(u[M]=Math.min(u[M],w[M]-1),h[M]=Math.min(h[M],w[M]-1),h[M]<u[M]){const e=h[M];h[M]=u[M],u[M]=e}const C=[h[0]-u[0]+1,h[1]-u[1]+1,h[2]-u[2]+1],k=C[0]*C[1]*C[2];let U=this.hdr.datatypeCode;if(g==="uint8"?U=NiiDataType.DT_UINT8:g==="float32"&&(U=NiiDataType.DT_FLOAT32),U===NiiDataType.DT_UINT8)v=new Uint8Array(k);else if(U===NiiDataType.DT_INT16)v=new Int16Array(k);else if(U===NiiDataType.DT_UINT16)v=new Uint16Array(k);else if(U===NiiDataType.DT_FLOAT32)v=new Float32Array(k);else if(U===NiiDataType.DT_FLOAT64)v=new Float64Array(k);else return log.error("getVolumeData unsupported datatype"),[v,[0,0,0]];const N=this.img2RASstep,O=this.img2RASstart;let d=0;for(let M=u[2];M<=h[2];M++){const e=O[2]+M*N[2];for(let b=u[1];b<=h[1];b++){const z=e+O[1]+b*N[1];for(let W=u[0];W<=h[0];W++){const s0=O[0]+W*N[0];v[d++]=this.img[s0+z]}}}return[v,C]}setVolumeData(u=[-1,0,0],h=[0,0,0],g=new Uint8Array){if(g.length<1||Math.min(...u)<0||Math.min(...h)<0)return;const v=this.dimsRAS.slice(1,4);for(let O=0;O<3;O++)if(u[O]=Math.min(u[O],v[O]-1),h[O]=Math.min(h[O],v[O]-1),h[O]<u[O]){const d=h[O];h[O]=u[O],u[O]=d}const w=[h[0]-u[0]+1,h[1]-u[1]+1,h[2]-u[2]+1],C=w[0]*w[1]*w[2];if(g.length<C){log.error("setVolumeData image does not have enough voxels");return}const k=this.img2RASstep,U=this.img2RASstart;let N=0;for(let O=u[2];O<=h[2];O++){const d=U[2]+O*k[2];for(let M=u[1];M<=h[1];M++){const e=d+U[1]+M*k[1];for(let b=u[0];b<=h[0];b++){const z=U[0]+b*k[0];this.img[z+e]=g[N++]}}}}static loadFromBase64({base64:u,name:h="",colormap:g="gray",opacity:v=1,cal_min:w=NaN,cal_max:C=NaN,trustCalMinMax:k=!0,percentileFrac:U=.02,ignoreZeroVoxels:N=!1,useQFormNotSForm:O=!1,colormapNegative:d="",frame4D:M=0,imageType:e=NVIMAGE_TYPE.UNKNOWN,cal_minNeg:b=NaN,cal_maxNeg:z=NaN,colorbarVisible:W=!0,colormapLabel:s0=null}){function K(D){const Z=window.atob(D),X=Z.length,r0=new Uint8Array(X);for(let l0=0;l0<X;l0++)r0[l0]=Z.charCodeAt(l0);return r0.buffer}let J=null;try{const D=K(u),Z=null;J=new NVImage(D,h,g,v,Z,w,C,k,U,N,O,d,M,e,b,z,W,s0)}catch(D){log.debug(D)}if(J===null)throw new Error("could not load NVImage");return J}clone(){const u=new NVImage;return u.id=v4(),u.hdr=Object.assign({},this.hdr),u.img=this.img.slice(),u.calculateRAS(),u.calMinMax(),u}zeroImage(){this.img.fill(0)}getImageMetadata(){if(!this.hdr)throw new Error("hdr undefined");const u=this.id,h=this.hdr.datatypeCode,g=this.hdr.dims,v=g[1],w=g[2],C=g[3],k=Math.max(1,g[4]),U=this.hdr.pixDims,N=U[1],O=U[2],d=U[3],M=U[4],e=Math.floor(this.hdr.numBitsPerVoxel/8);return{id:u,datatypeCode:h,nx:v,ny:w,nz:C,nt:k,dx:N,dy:O,dz:d,dt:M,bpv:e}}static zerosLike(u,h="same"){const g=u.clone();return g.zeroImage(),h==="uint8"&&(g.img=Uint8Array.from(g.img),g.hdr.datatypeCode=NiiDataType.DT_UINT8,g.hdr.numBitsPerVoxel=8),h==="float32"&&(g.img=Float32Array.from(g.img),g.hdr.datatypeCode=NiiDataType.DT_FLOAT32,g.hdr.numBitsPerVoxel=32),g}getValue(u,h,g,v=0,w=!1){if(!this.hdr)throw new Error("hdr undefined");if(!this.img)throw new Error("img undefined");const C=this.hdr.dims[1],k=this.hdr.dims[2],U=this.hdr.dims[3],N=this.permRAS.slice();if(N[0]!==1||N[1]!==2||N[2]!==3){const e=fromValues$1(u,h,g,1);transformMat4(e,e,this.toRASvox),u=e[0],h=e[1],g=e[2]}let O=u+h*C+g*C*k;if(this.hdr.datatypeCode===NiiDataType.DT_RGBA32)return O*=4,Math.round(this.img[O]*.21+this.img[O+1]*.72+this.img[O+2]*.07);if(this.hdr.datatypeCode===NiiDataType.DT_RGB24)return O*=3,Math.round(this.img[O]*.21+this.img[O+1]*.72+this.img[O+2]*.07);const d=v*C*k*U;let M=this.img[O+d];return w&&(M=this.imaginary[O+d]),this.hdr.scl_slope*M+this.hdr.scl_inter}toNiivueObject3D(u,h){const g=this.dimsRAS,v=this.matRAS,w=this.pixDimsRAS,C=-.5,k=-.5,U=-.5,N=g[1]-1+.5,O=g[2]-1+.5,d=g[3]-1+.5,M=this.vox2mm([C,k,U],v),e=this.vox2mm([C,O,U],v),b=this.vox2mm([C,k,d],v),z=this.vox2mm([C,O,d],v),W=this.vox2mm([N,k,U],v),s0=this.vox2mm([N,O,U],v),K=this.vox2mm([N,k,d],v),J=this.vox2mm([N,O,d],v),D=[...b,0,0,1,...K,1,0,1,...J,1,1,1,...z,0,1,1,...M,0,0,0,...e,0,1,0,...s0,1,1,0,...W,1,0,0],Z=h.createBuffer();h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,Z);const X=[0,3,2,2,1,0,4,7,6,6,5,4,5,6,2,2,3,5,4,0,1,1,7,4,7,1,2,2,6,7,4,5,3,3,0,4];h.bufferData(h.ELEMENT_ARRAY_BUFFER,new Uint16Array(X),h.STATIC_DRAW);const r0=h.createBuffer();h.bindBuffer(h.ARRAY_BUFFER,r0),h.bufferData(h.ARRAY_BUFFER,new Float32Array(D),h.STATIC_DRAW);const l0=h.createVertexArray();h.bindVertexArray(l0),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,Z),h.bindBuffer(h.ARRAY_BUFFER,r0),h.enableVertexAttribArray(0),h.vertexAttribPointer(0,3,h.FLOAT,!1,24,0),h.enableVertexAttribArray(1),h.vertexAttribPointer(1,3,h.FLOAT,!1,24,12),h.bindVertexArray(null);const j=new NiivueObject3D(u,r0,h.TRIANGLES,X.length,Z,l0),f=getExtents([...b,...K,...J,...z,...M,...e,...s0,...W]);return j.extentsMin=f.min.slice(),j.extentsMax=f.max.slice(),j.furthestVertexFromOrigin=f.furthestVertexFromOrigin,j.originNegate=clone$1(f.origin),negate(j.originNegate,j.originNegate),j.fieldOfViewDeObliqueMM=[g[1]*w[1],g[2]*w[2],g[3]*w[3]],j}applyOptionsUpdate(u){this.hdr.cal_min=u.cal_min,this.hdr.cal_max=u.cal_max,Object.assign(this,u)}getImageOptions(){return NVImageFromUrlOptions("","",this.name,this._colormap,this.opacity,this.hdr.cal_min,this.hdr.cal_max,this.trustCalMinMax,this.percentileFrac,this.ignoreZeroVoxels,this.useQFormNotSForm,this.colormapNegative,this.frame4D,this.imageType)}toUint8Array(u=null){const h=u!==null,g=hdrToArrayBuffer(this.hdr,h);let v=u;if(h){const U=this.permRAS;if(U[0]!==1||U[1]!==2||U[2]!==3){const N=this.hdr.dims,O=[0,0,0];for(let D=0;D<3;D++)for(let Z=0;Z<3;Z++)Math.abs(U[D])-1===Z&&(O[Z]=D*Math.sign(U[D]));let d=1;const M=[1,1,1],e=[!1,!1,!1];for(let D=0;D<O.length;D++)for(let Z=0;Z<O.length;Z++)Math.abs(O[Z])===D&&(M[Z]=d,(O[Z]<0||Object.is(O[Z],-0))&&(e[Z]=!0),d*=N[Z+1]);let b=NVUtilities.range(0,N[1]-1,1);e[0]&&(b=NVUtilities.range(N[1]-1,0,-1));for(let D=0;D<N[1];D++)b[D]*=M[0];let z=NVUtilities.range(0,N[2]-1,1);e[1]&&(z=NVUtilities.range(N[2]-1,0,-1));for(let D=0;D<N[2];D++)z[D]*=M[1];let W=NVUtilities.range(0,N[3]-1,1);e[2]&&(W=NVUtilities.range(N[3]-1,0,-1));for(let D=0;D<N[3];D++)W[D]*=M[2];const s0=new Uint8Array(u),K=new Uint8Array(N[1]*N[2]*N[3]);let J=0;for(let D=0;D<N[3];D++)for(let Z=0;Z<N[2];Z++)for(let X=0;X<N[1];X++)K[J]=s0[b[X]+z[Z]+W[D]],J++;v=K,log.debug("drawing bytes"),log.debug(v)}}const w=h?v:new Uint8Array(this.img.buffer),C=new Uint8Array(4),k=new Uint8Array(g.length+C.length+w.length);return k.set(g),k.set(C,g.length),k.set(w,g.length+C.length),k}convertVox2Frac(u){return fromValues$2((u[0]+.5)/this.dimsRAS[1],(u[1]+.5)/this.dimsRAS[2],(u[2]+.5)/this.dimsRAS[3])}convertFrac2Vox(u){return fromValues$2(Math.round(u[0]*this.dims[1]-.5),Math.round(u[1]*this.dims[2]-.5),Math.round(u[2]*this.dims[3]-.5))}convertFrac2MM(u,h=!1){const g=fromValues$1(u[0],u[1],u[2],1);return h?transformMat4(g,g,this.frac2mm):transformMat4(g,g,this.frac2mmOrtho),g}convertMM2Frac(u,h=!1){const g=fromValues$1(u[0],u[1],u[2],1),v=this.dimsRAS,w=fromValues$2(0,0,0);if(typeof v>"u")return w;if(!h){const k=clone$2(this.frac2mmOrtho);return invert(k,k),transformMat4(g,g,k),w[0]=g[0],w[1]=g[1],w[2]=g[2],w}if(v[1]<1||v[2]<1||v[3]<1)return w;const C=clone$2(this.matRAS);return invert(C,C),transpose(C,C),transformMat4(g,g,C),w[0]=(g[0]+.5)/v[1],w[1]=(g[1]+.5)/v[2],w[2]=(g[2]+.5)/v[3],w}}var SLICE_TYPE=(T=>(T[T.AXIAL=0]="AXIAL",T[T.CORONAL=1]="CORONAL",T[T.SAGITTAL=2]="SAGITTAL",T[T.MULTIPLANAR=3]="MULTIPLANAR",T[T.RENDER=4]="RENDER",T))(SLICE_TYPE||{}),MULTIPLANAR_TYPE=(T=>(T[T.AUTO=0]="AUTO",T[T.COLUMN=1]="COLUMN",T[T.GRID=2]="GRID",T[T.ROW=3]="ROW",T))(MULTIPLANAR_TYPE||{}),DRAG_MODE=(T=>(T[T.none=0]="none",T[T.contrast=1]="contrast",T[T.measurement=2]="measurement",T[T.pan=3]="pan",T[T.slicer3D=4]="slicer3D",T[T.callbackOnly=5]="callbackOnly",T))(DRAG_MODE||{});const DEFAULT_OPTIONS={textHeight:.06,colorbarHeight:.05,crosshairWidth:1,crosshairGap:0,rulerWidth:4,show3Dcrosshair:!1,backColor:[0,0,0,1],crosshairColor:[1,0,0,1],fontColor:[.5,.5,.5,1],selectionBoxColor:[1,1,1,.5],clipPlaneColor:[.7,0,.7,.5],rulerColor:[1,0,0,.8],colorbarMargin:.05,trustCalMinMax:!0,clipPlaneHotKey:"KeyC",viewModeHotKey:"KeyV",doubleTouchTimeout:500,longTouchTimeout:1e3,keyDebounceTime:50,isNearestInterpolation:!1,isResizeCanvas:!0,atlasOutline:0,isRuler:!1,isColorbar:!1,isOrientCube:!1,multiplanarPadPixels:0,multiplanarForceRender:!1,isRadiologicalConvention:!1,meshThicknessOn2D:1/0,dragMode:1,yoke3Dto2DZoom:!1,isDepthPickMesh:!1,isCornerOrientationText:!1,sagittalNoseLeft:!1,isSliceMM:!1,isV1SliceShader:!1,isHighResolutionCapable:!0,logLevel:"info",loadingText:"waiting for images...",isForceMouseClickToVoxelCenters:!1,dragAndDropEnabled:!0,drawingEnabled:!1,penValue:1,floodFillNeighbors:6,isFilledPen:!1,thumbnail:"",maxDrawUndoBitmaps:8,sliceType:3,meshXRay:0,isAntiAlias:null,limitFrames4D:NaN,isAdditiveBlend:!1,showLegend:!0,legendBackgroundColor:[.3,.3,.3,.5],legendTextColor:[1,1,1,1],multiplanarLayout:0,renderOverlayBlend:1,sliceMosaicString:""},INITIAL_SCENE_DATA={azimuth:110,elevation:10,crosshairPos:fromValues$2(.5,.5,.5),clipPlane:[0,0,0,0],clipPlaneDepthAziElev:[2,0,0],volScaleMultiplier:1,pan2Dxyzmm:fromValues$1(0,0,0,1)};class NVDocument{constructor(){g0(this,"data",{title:"Untitled document",imageOptionsArray:[],meshOptionsArray:[],opts:{...DEFAULT_OPTIONS},previewImageDataURL:"",labels:[],encodedImageBlobs:[],encodedDrawingBlob:""});g0(this,"scene");g0(this,"volumes",[]);g0(this,"meshDataObjects");g0(this,"meshes",[]);g0(this,"drawBitmap",null);g0(this,"imageOptionsMap",new Map);g0(this,"meshOptionsMap",new Map);this.scene={onAzimuthElevationChange:()=>{},onZoom3DChange:()=>{},sceneData:INITIAL_SCENE_DATA,get renderAzimuth(){return this.sceneData.azimuth},set renderAzimuth(u){this.sceneData.azimuth=u,this.onAzimuthElevationChange&&this.onAzimuthElevationChange(this.sceneData.azimuth,this.sceneData.elevation)},get renderElevation(){return this.sceneData.elevation},set renderElevation(u){this.sceneData.elevation=u,this.onAzimuthElevationChange&&this.onAzimuthElevationChange(this.sceneData.azimuth,this.sceneData.elevation)},get volScaleMultiplier(){return this.sceneData.volScaleMultiplier},set volScaleMultiplier(u){this.sceneData.volScaleMultiplier=u,this.onZoom3DChange(u)},get crosshairPos(){return this.sceneData.crosshairPos},set crosshairPos(u){this.sceneData.crosshairPos=u},get clipPlane(){return this.sceneData.clipPlane},set clipPlane(u){this.sceneData.clipPlane=u},get clipPlaneDepthAziElev(){return this.sceneData.clipPlaneDepthAziElev},set clipPlaneDepthAziElev(u){this.sceneData.clipPlaneDepthAziElev=u},get pan2Dxyzmm(){return this.sceneData.pan2Dxyzmm},set pan2Dxyzmm(u){this.sceneData.pan2Dxyzmm=u}}}get title(){return this.data.title}get previewImageDataURL(){return this.data.previewImageDataURL}set previewImageDataURL(u){this.data.previewImageDataURL=u}set title(u){this.data.title=u}get imageOptionsArray(){return this.data.imageOptionsArray}get encodedImageBlobs(){return this.data.encodedImageBlobs}get encodedDrawingBlob(){return this.data.encodedDrawingBlob}get opts(){return this.data.opts}set opts(u){this.data.opts={...u}}get labels(){return this.data.labels}set labels(u){this.data.labels=u}hasImage(u){return this.volumes.find(h=>h.id===u.id)!==void 0}hasImageFromUrl(u){return this.data.imageOptionsArray.find(h=>h.url===u)!==void 0}addImageOptions(u,h){if(!this.hasImage(u)&&!h.name)if(h.url){const v=/^(?:[a-z+]+:)?\/\//i.test(h.url)?new URL(h.url):new URL(h.url,window.location.href);h.name=v.pathname.split("/").pop(),h.name.toLowerCase().endsWith(".gz")&&(h.name=h.name.slice(0,-3)),h.name.toLowerCase().endsWith(".nii")||(h.name+=".nii")}else h.name="untitled.nii";h.imageType=NVIMAGE_TYPE.NII,this.data.imageOptionsArray.push(h),this.imageOptionsMap.set(u.id,this.data.imageOptionsArray.length-1)}removeImage(u){if(this.imageOptionsMap.has(u.id)){const h=this.imageOptionsMap.get(u.id);this.data.imageOptionsArray.length>h&&this.data.imageOptionsArray.splice(h,1),this.imageOptionsMap.delete(u.id)}this.volumes=this.volumes.filter(h=>h.id!==u.id)}getImageOptions(u){return this.imageOptionsMap.has(u.id)?this.data.imageOptionsArray[this.imageOptionsMap.get(u.id)]:null}json(){const u={encodedImageBlobs:[],previewImageDataURL:this.data.previewImageDataURL,imageOptionsMap:new Map},h=[];if(u.sceneData={...this.scene.sceneData},u.opts={...this.opts},this.opts.meshThicknessOn2D===1/0&&(u.opts.meshThicknessOn2D="infinity"),u.labels=[...this.data.labels],this.volumes.length){let v=this.imageOptionsArray[0];if(v||(log.debug("no image options for base image"),v={name:"",colormap:"gray",opacity:1,pairedImgData:null,cal_min:NaN,cal_max:NaN,trustCalMinMax:!0,percentileFrac:.02,ignoreZeroVoxels:!1,useQFormNotSForm:!1,colormapNegative:"",colormapLabel:null,imageType:NVIMAGE_TYPE.NII,frame4D:0,limitFrames4D:NaN,url:"",urlImageData:"",alphaThreshold:!1,cal_minNeg:NaN,cal_maxNeg:NaN,colorbarVisible:!0}),v.colormap=this.volumes[0].colormap,v.opacity=this.volumes[0].opacity,v.cal_max=this.volumes[0].cal_max||NaN,v.cal_min=this.volumes[0].cal_min||NaN,v){h.push(v);const w=NVUtilities.uint8tob64(this.volumes[0].toUint8Array());u.encodedImageBlobs.push(w),this.drawBitmap&&(u.encodedDrawingBlob=NVUtilities.uint8tob64(this.volumes[0].toUint8Array(this.drawBitmap))),u.imageOptionsMap.set(this.volumes[0].id,0)}else throw new Error("image options for base layer not found");for(let w=1;w<this.volumes.length;w++){const C=this.volumes[w];let k=this.getImageOptions(C);k===null?(log.warn("no options found for image, using default"),k={name:"",colormap:"gray",opacity:1,pairedImgData:null,cal_min:NaN,cal_max:NaN,trustCalMinMax:!0,percentileFrac:.02,ignoreZeroVoxels:!1,useQFormNotSForm:!1,colormapNegative:"",colormapLabel:null,imageType:NVIMAGE_TYPE.NII,frame4D:0,limitFrames4D:NaN,url:"",urlImageData:"",alphaThreshold:!1,cal_minNeg:NaN,cal_maxNeg:NaN,colorbarVisible:!0}):"imageType"in k||(k.imageType=NVIMAGE_TYPE.NII),k.colormap=C.colormap,k.colormapLabel=C.colormapLabel,k.opacity=C.opacity,k.cal_max=C.cal_max||NaN,k.cal_min=C.cal_min||NaN,h.push(k);const U=NVUtilities.uint8tob64(C.toUint8Array());u.encodedImageBlobs.push(U),u.imageOptionsMap.set(C.id,w)}}u.imageOptionsArray=[...h];const g=[];u.connectomes=[];for(const v of this.meshes){if(v.type===MeshType.CONNECTOME){u.connectomes.push(JSON.stringify(v.json()));continue}const w={pts:v.pts,tris:v.tris,name:v.name,rgba255:Uint8Array.from(v.rgba255),opacity:v.opacity,connectome:v.connectome,dpg:v.dpg,dps:v.dps,dpv:v.dpv,meshShaderIndex:v.meshShaderIndex,layers:v.layers.map(C=>({values:C.values,nFrame4D:C.nFrame4D,frame4D:0,outlineBorder:C.outlineBorder,global_min:C.global_min,global_max:C.global_max,cal_min:C.cal_min,cal_max:C.cal_max,opacity:C.opacity,colormap:C.colormap,colormapNegative:C.colormapNegative,colormapLabel:C.colormapLabel,useNegativeCmap:C.useNegativeCmap})),hasConnectome:v.hasConnectome,edgeColormap:v.edgeColormap,edgeColormapNegative:v.edgeColormapNegative,edgeMax:v.edgeMax,edgeMin:v.edgeMin,edges:v.edges&&Array.isArray(v.edges)?[...v.edges]:[],extentsMax:v.extentsMax,extentsMin:v.extentsMin,fiberGroupColormap:v.fiberGroupColormap,furthestVertexFromOrigin:v.furthestVertexFromOrigin,nodeColormap:v.nodeColormap,nodeColormapNegative:v.nodeColormapNegative,nodeMaxColor:v.nodeMaxColor,nodeMinColor:v.nodeMinColor,nodeScale:v.nodeScale,legendLineThickness:v.legendLineThickness,offsetPt0:v.offsetPt0,nodes:v.nodes};g.push(w)}return u.meshesString=JSON.stringify(serialize(g)),u}download(u){const h=this.json();NVUtilities.download(JSON.stringify(h),u,"application/json")}static deserializeMeshDataObjects(u){if(u.data.meshesString){u.meshDataObjects=deserialize(JSON.parse(u.data.meshesString));for(const h of u.meshDataObjects)for(const g of h.layers)"colorMap"in g&&(g.colormap=g.colorMap,delete g.colorMap),"colorMapNegative"in g&&(g.colormapNegative=g.colorMapNegative,delete g.colorMapNegative)}}static async loadFromUrl(u){const g=await(await fetch(u)).json();return NVDocument.loadFromJSON(g)}static async loadFromFile(u){const h=await NVUtilities.readFileAsync(u),g=new NVDocument,w=new TextDecoder().decode(h);return g.data=JSON.parse(w),g.data.opts.meshThicknessOn2D==="infinity"&&(g.data.opts.meshThicknessOn2D=1/0),g.scene.sceneData={...INITIAL_SCENE_DATA,...g.data.sceneData},NVDocument.deserializeMeshDataObjects(g),g}static loadFromJSON(u){const h=new NVDocument;return h.data=u,h.data.opts.meshThicknessOn2D==="infinity"&&(h.data.opts.meshThicknessOn2D=1/0),h.scene.sceneData={...INITIAL_SCENE_DATA,...u.sceneData},NVDocument.deserializeMeshDataObjects(h),h}}var LabelTextAlignment=(T=>(T.LEFT="left",T.RIGHT="right",T.CENTER="center",T))(LabelTextAlignment||{}),LabelLineTerminator=(T=>(T.NONE="none",T.CIRCLE="circle",T.RING="ring",T))(LabelLineTerminator||{});class NVLabel3DStyle{constructor(u=[1,1,1,1],h=1,g="left",v=0,w=[0,0,0],C="none",k,U,N){g0(this,"textColor");g0(this,"textScale");g0(this,"textAlignment");g0(this,"lineWidth");g0(this,"lineColor");g0(this,"lineTerminator");g0(this,"bulletScale");g0(this,"bulletColor");g0(this,"backgroundColor");this.textColor=u,this.textScale=h,this.textAlignment=g,this.lineWidth=v,this.lineColor=w,this.lineTerminator=C,this.bulletScale=k,this.bulletColor=U,this.backgroundColor=N}}class NVLabel3D{constructor(u,h,g){g0(this,"text");g0(this,"style");g0(this,"points");this.text=u,this.style=h,this.points=g}}const defaultOptions={name:"untitled connectome",nodeColormap:"warm",nodeColormapNegative:"winter",nodeMinColor:0,nodeMaxColor:4,nodeScale:3,edgeColormap:"warm",edgeColormapNegative:"winter",edgeMin:2,edgeMax:6,edgeScale:1,legendLineThickness:0};class NVConnectome extends NVMesh{constructor(h,g){super(new Float32Array([]),new Uint32Array([]),g.name,new Uint8Array([]),1,!0,h,g);g0(this,"gl");g0(this,"nodesChanged");this.gl=h,this.type=MeshType.CONNECTOME,this.nodes&&this.updateLabels(),this.nodesChanged=new EventTarget}static convertLegacyConnectome(h){const g={nodes:[],edges:[],...defaultOptions};for(const w in h)if(w in defaultOptions){const C=w;g[C]=h[C]}const v=h.nodes;for(let w=0;w<v.names.length;w++)g.nodes.push({name:v.names[w],x:v.X[w],y:v.Y[w],z:v.Z[w],colorValue:v.Color[w],sizeValue:v.Size[w]});for(let w=0;w<v.names.length-1;w++)for(let C=w+1;C<v.names.length;C++){const k=h.edges[w*v.names.length+C];g.edges.push({first:w,second:C,colorValue:k})}return g}static convertFreeSurferConnectome(h,g="warm"){let v=!0;if("data_type"in h?h.data_type!=="fs_pointset"&&(v=!1):v=!1,"points"in h||(v=!1),!v)throw Error("not a valid FreeSurfer json pointset");const w=h.points.map(k=>({name:Array.isArray(k.comments)&&k.comments.length>0&&"text"in k.comments[0]?k.comments[0].text:"",x:k.coordinates.x,y:k.coordinates.y,z:k.coordinates.z,colorValue:1,sizeValue:1,metadata:k.comments}));return{...defaultOptions,nodeColormap:g,edgeColormap:g,nodes:w,edges:[]}}updateLabels(){const h=this.nodes;if(h&&h.length>0){const g=h.reduce((O,d)=>O.sizeValue>d.sizeValue?O:d).sizeValue,v=this.nodeMinColor?this.nodeMinColor:h.reduce((O,d)=>O.colorValue<d.colorValue?O:d).colorValue,w=this.nodeMaxColor?this.nodeMaxColor:h.reduce((O,d)=>O.colorValue>d.colorValue?O:d).colorValue,C=cmapper.colormap(this.nodeColormap,this.colormapInvert),k=cmapper.colormap(this.nodeColormapNegative,this.colormapInvert),U="nodeColormapNegative"in this,N=this.legendLineThickness?this.legendLineThickness:0;for(let O=0;O<h.length;O++){let d=h[O].colorValue,M=!1;if(U&&d<0&&(M=!0,d=-d),v<w){if(d<v){log.warn("color value lower than min");continue}d=(d-v)/(w-v)}else d=1;d=Math.round(Math.max(Math.min(255,d*255)))*4;let e=[C[d],C[d+1],C[d+2],255];M&&(e=[k[d],k[d+1],k[d+2],255]),e=e.map(b=>b/255),log.debug("adding label for ",h[O]),h[O].label=new NVLabel3D(h[O].name,{textColor:e,bulletScale:h[O].sizeValue/g,bulletColor:e,lineWidth:N,lineColor:e,textScale:1,textAlignment:LabelTextAlignment.LEFT,lineTerminator:LabelLineTerminator.NONE},[h[O].x,h[O].y,h[O].z]),log.debug("label for node:",h[O].label)}}}addConnectomeNode(h){if(log.debug("adding node",h),!this.nodes)throw new Error("nodes not defined");this.nodes.push(h),this.updateLabels(),this.nodesChanged.dispatchEvent(new CustomEvent("nodeAdded",{detail:{node:h}}))}deleteConnectomeNode(h){const g=this.nodes.indexOf(h),v=this.edges;v&&(this.edges=v.filter(w=>w.first!==g&&w.second!==g)),this.nodes=this.nodes.filter(w=>w!==h),this.updateLabels(),this.updateConnectome(this.gl),this.nodesChanged.dispatchEvent(new CustomEvent("nodeDeleted",{detail:{node:h}}))}updateConnectomeNodeByIndex(h,g){this.nodes[h]=g,this.updateLabels(),this.updateConnectome(this.gl),this.nodesChanged.dispatchEvent(new CustomEvent("nodeChanged",{detail:{node:g}}))}updateConnectomeNodeByPoint(h,g){const v=this.nodes;if(!v)throw new Error("Node to update does not exist");const w=v.find(k=>NVUtilities.arraysAreEqual([k.x,k.y,k.z],h));if(!w)throw new Error(`Node with point ${h} to update does not exist`);const C=v.findIndex(k=>k===w);this.updateConnectomeNodeByIndex(C,g)}addConnectomeEdge(h,g,v){const w=this.edges;let C=w.find(k=>(k.first===h||k.second===h)&&k.first+k.second===h+g);return C||(C={first:h,second:g,colorValue:v},w.push(C),this.updateConnectome(this.gl),C)}deleteConnectomeEdge(h,g){const v=this.edges,w=v.find(C=>(C.first===h||C.first===g)&&C.first+C.second===h+g);if(w)this.edges=v.filter(C=>C!==w);else throw new Error(`edge between ${h} and ${g} not found`);return this.updateConnectome(this.gl),w}findClosestConnectomeNode(h,g){const v=this.nodes;if(!v||v.length===0)return null;const w=v.map((C,k)=>({node:C,distance:Math.sqrt(Math.pow(C.x-h[0],2)+Math.pow(C.y-h[1],2)+Math.pow(C.z-h[2],2)),index:k})).filter(C=>C.distance<g).sort((C,k)=>C.distance-k.distance);return w.length>0?w[0].node:null}updateConnectome(h){const g=[],v=[],w=[];let C=cmapper.colormap(this.nodeColormap,this.colormapInvert),k=cmapper.colormap(this.nodeColormapNegative,this.colormapInvert),U="nodeColormapNegative"in this;if(this.nodeMinColor===void 0||this.nodeMaxColor===void 0)throw new Error("nodeMinColor or nodeMaxColor is undefined");if(this.edgeMin===void 0||this.edgeMax===void 0)throw new Error("edgeMin or edgeMax undefined");let N=this.nodeMinColor,O=this.nodeMaxColor;const d=this.nodes,M=d.length;for(let K=0;K<M;K++){const J=d[K].sizeValue*this.nodeScale;if(J<=0)continue;let D=d[K].colorValue,Z=!1;if(U&&D<0&&(Z=!0,D=-D),N<O){if(D<N)continue;D=(D-N)/(O-N)}else D=1;D=Math.round(Math.max(Math.min(255,D*255)))*4;let X=[C[D],C[D+1],C[D+2],255];Z&&(X=[k[D],k[D+1],k[D+2],255]);const r0=fromValues$2(d[K].x,d[K].y,d[K].z);NiivueObject3D.makeColoredSphere(v,g,w,J,r0,X)}C=cmapper.colormap(this.edgeColormap,this.colormapInvert),k=cmapper.colormap(this.edgeColormapNegative,this.colormapInvert),U="edgeColormapNegative"in this,N=this.edgeMin,O=this.edgeMax;const e=this.edges;for(const K of e){let J=K.colorValue;const D=U&&J<0;D&&(J=-J);const Z=J*this.edgeScale;if(Z<=0)continue;if(N<O){if(J<N)continue;J=(J-N)/(O-N)}else J=1;J=Math.round(Math.max(Math.min(255,J*255)))*4;let X=[C[J],C[J+1],C[J+2],255];D&&(X=[k[J],k[J+1],k[J+2],255]);const r0=fromValues$2(d[K.first].x,d[K.first].y,d[K.first].z),l0=fromValues$2(d[K.second].x,d[K.second].y,d[K.second].z);NiivueObject3D.makeColoredCylinder(v,g,w,r0,l0,Z,X)}const b=new Float32Array(v),z=new Uint32Array(g),W=NVMeshUtilities.getExtents(b);this.furthestVertexFromOrigin=W.mxDx,this.extentsMin=W.extentsMin,this.extentsMax=W.extentsMax;const s0=this.generatePosNormClr(b,z,new Uint8Array(w));h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),h.bufferData(h.ELEMENT_ARRAY_BUFFER,Uint32Array.from(z),h.STATIC_DRAW),h.bindBuffer(h.ARRAY_BUFFER,this.vertexBuffer),h.bufferData(h.ARRAY_BUFFER,Float32Array.from(s0),h.STATIC_DRAW),this.indexCount=g.length}updateMesh(h){this.updateConnectome(h),this.updateLabels()}json(){const h={};for(const g in this)(g in defaultOptions||g==="nodes"||g==="edges")&&(h[g]=this[g]);return h}static async loadConnectomeFromUrl(h,g){const w=await(await fetch(g)).json();return new NVConnectome(h,w)}}function img2ras16(T){const u=T.hdr.dims,h=T.permRAS,g=u[1]*u[2]*u[3],v=new Int16Array(g),w=[0,0,0];for(let e=0;e<3;e++)for(let b=0;b<3;b++)Math.abs(h[e])-1===b&&(w[b]=e*Math.sign(h[e]));let C=1;const k=[1,1,1],U=[!1,!1,!1];for(let e=0;e<w.length;e++)for(let b=0;b<w.length;b++)Math.abs(w[b])===e&&(k[b]=C,(w[b]<0||Object.is(w[b],-0))&&(U[b]=!0),C*=u[b+1]);let N=NVUtilities.range(0,u[1]-1,1);U[0]&&(N=NVUtilities.range(u[1]-1,0,-1));for(let e=0;e<u[1];e++)N[e]*=k[0];let O=NVUtilities.range(0,u[2]-1,1);U[1]&&(O=NVUtilities.range(u[2]-1,0,-1));for(let e=0;e<u[2];e++)O[e]*=k[1];let d=NVUtilities.range(0,u[3]-1,1);U[2]&&(d=NVUtilities.range(u[3]-1,0,-1));for(let e=0;e<u[3];e++)d[e]*=k[2];let M=0;for(let e=0;e<u[3];e++)for(let b=0;b<u[2];b++)for(let z=0;z<u[1];z++)v[N[z]+O[b]+d[e]]=T.img[M],M++;return v}function nice(T,u){const h=Math.floor(Math.log(T)/Math.log(10)),g=T/Math.pow(10,h);let v;return u?g<1.5?v=1:g<3?v=2:g<7?v=5:v=10:g<=1?v=1:g<=2?v=2:g<=5?v=5:v=10,v*Math.pow(10,h)}function loose_label(T,u,h=4){const g=nice(u-T,!1),v=nice(g/(h-1),!0),w=Math.floor(T/v)*v,C=Math.ceil(u/v)*v;return[v,w,C,w===T&&C===u]}function tickSpacing(T,u){let h=loose_label(T,u,3);return h[3]||(h=loose_label(T,u,5)),h[3]||(h=loose_label(T,u,4)),h[3]||(h=loose_label(T,u,3)),h[3]||(h=loose_label(T,u,5)),[h[0],h[1],h[2]]}function deg2rad(T){return T*(Math.PI/180)}function negMinMax(T,u,h,g){let v=-T,w=-u;return isFinite(h)&&isFinite(g)&&(v=h,w=g),v>w&&([v,w]=[w,v]),[v,w]}function swizzleVec3(T,u=[0,1,2]){const h=create$2();return h[0]=T[u[0]],h[1]=T[u[1]],h[2]=T[u[2]],h}function isRadiological(T){const u=fromValues$1(1,0,0,0),h=create$1();return transformMat4(h,u,T),h[0]}function unProject(T,u,h,g){const v=fromValues$1(T,u,h,1),w=clone$2(g);invert(w,w),v[0]=v[0]*2-1,v[1]=v[1]*2-1,v[2]=v[2]*2-1;const C=create$1();return transformMat4(C,v,w),C[3]===0||(C[0]/=C[3],C[1]/=C[3],C[2]/=C[3]),C}function unpackFloatFromVec4i(T){const u=[5960464477539063e-23,152587890625e-16,.00390625,1];return(T[0]*u[0]+T[1]*u[1]+T[2]*u[2]+T[3]*u[3])/255}function clamp(T,u,h){return Math.min(Math.max(T,u),h)}function encodeRLE(T){const u=T.length;let h=0;const g=new Uint8Array(u+Math.ceil(.01*u)),v=new Int8Array(g.buffer);let w=0;for(;h<u;){let C=T[h];h++;let k=1;for(;k<129&&h<u&&T[h]===C;)h++,k++;if(k>1){v[w]=-k+1,w++,g[w]=C,w++;continue}for(;h<u&&!(k>127||h+2<u&&C!==T[h]&&T[h+2]===T[h]&&T[h+1]===T[h]);)C=T[h],h++,k++;g[w]=k-1,w++;for(let U=0;U<k;U++)g[w]=T[h-k+U],w++}return log.info("PackBits "+u+" -> "+w+" bytes (x"+u/w+")"),g.slice(0,w)}function decodeRLE(T,u){const h=new Uint8Array(T.buffer),g=new Int8Array(h.buffer);let v=0;const w=new Uint8Array(u);let C=0;for(;v<h.length;){const k=g[v];if(v++,k<0){const U=g[v];v++;for(let N=0;N<1-k;N++)w[C]=U,C++}else for(let U=0;U<k+1;U++)w[C]=g[v],v++,C++}return w}function intensityRaw2Scaled(T,u){return T.scl_slope===0&&(T.scl_slope=1),u*T.scl_slope+T.scl_inter}var extendStatics=function(T,u){return extendStatics=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(h,g){h.__proto__=g}||function(h,g){for(var v in g)Object.prototype.hasOwnProperty.call(g,v)&&(h[v]=g[v])},extendStatics(T,u)};function __extends(T,u){if(typeof u!="function"&&u!==null)throw new TypeError("Class extends value "+String(u)+" is not a constructor or null");extendStatics(T,u);function h(){this.constructor=T}T.prototype=u===null?Object.create(u):(h.prototype=u.prototype,new h)}var __assign=function(){return __assign=Object.assign||function(u){for(var h,g=1,v=arguments.length;g<v;g++){h=arguments[g];for(var w in h)Object.prototype.hasOwnProperty.call(h,w)&&(u[w]=h[w])}return u},__assign.apply(this,arguments)};function __values(T){var u=typeof Symbol=="function"&&Symbol.iterator,h=u&&T[u],g=0;if(h)return h.call(T);if(T&&typeof T.length=="number")return{next:function(){return T&&g>=T.length&&(T=void 0),{value:T&&T[g++],done:!T}}};throw new TypeError(u?"Object is not iterable.":"Symbol.iterator is not defined.")}function __read(T,u){var h=typeof Symbol=="function"&&T[Symbol.iterator];if(!h)return T;var g=h.call(T),v,w=[],C;try{for(;(u===void 0||u-- >0)&&!(v=g.next()).done;)w.push(v.value)}catch(k){C={error:k}}finally{try{v&&!v.done&&(h=g.return)&&h.call(g)}finally{if(C)throw C.error}}return w}function __spreadArray(T,u,h){if(h||arguments.length===2)for(var g=0,v=u.length,w;g<v;g++)(w||!(g in u))&&(w||(w=Array.prototype.slice.call(u,0,g)),w[g]=u[g]);return T.concat(w||Array.prototype.slice.call(u))}typeof SuppressedError=="function"&&SuppressedError;function isFunction(T){return typeof T=="function"}function createErrorClass(T){var u=function(g){Error.call(g),g.stack=new Error().stack},h=T(u);return h.prototype=Object.create(Error.prototype),h.prototype.constructor=h,h}var UnsubscriptionError=createErrorClass(function(T){return function(h){T(this),this.message=h?h.length+` errors occurred during unsubscription:
1614
+ `),d=/(.*\/).*/.exec(v)[0],M=[];for(const e of N){const b=new URL(e,d);if(k=await fetch(b,{headers:h}),!k.ok)throw Error(k.statusText);const z=await k.arrayBuffer();M.push(z)}return M}static async fetchPartial(u,h,g={}){try{return await fetch(u,{headers:{range:`bytes=0-'${h}`,stream:"true",...g}})}catch(v){return log.error(v),log.error("fetchPartial failed, trying again without range header"),await fetch(u,{headers:g})}}static async loadFromUrl({url:u="",urlImgData:h="",headers:g={},name:v="",colormap:w="gray",opacity:C=1,cal_min:k=NaN,cal_max:U=NaN,trustCalMinMax:N=!0,percentileFrac:O=.02,ignoreZeroVoxels:d=!1,useQFormNotSForm:M=!1,colormapNegative:e="",frame4D:b=0,isManifest:z=!1,limitFrames4D:W=NaN,imageType:s0=NVIMAGE_TYPE.UNKNOWN,colorbarVisible:K=!0,buffer:J=new ArrayBuffer(0)}={}){if(u==="")throw Error("url must not be empty");let D=null,Z=null;if(u instanceof Uint8Array&&(u=u.buffer),J.byteLength>0&&(u=J),u instanceof ArrayBuffer)if(Z=u,v!=="")u=v;else{u="array.nii";const f=new Uint8Array(Z);f[0]===31&&f[1]===139&&(u="array.nii.gz")}if(!isNaN(W)){let f=await this.fetchPartial(u,512,g);Z=await f.arrayBuffer();let c0=new Uint8Array(Z),h0=!1;c0[0]===31&&c0[1]===139&&(h0=!0,new Decompress$1(x0=>{c0=x0}).push(c0),Z=c0.buffer);let A0=c0[0]===92&&c0[1]===1;if(A0||(A0=c0[1]===92&&c0[0]===1),!A0)Z=null;else{const w0=nifti.readHeader(Z);if(w0===null)throw new Error("could not read nifti header");const x0=w0.numBitsPerVoxel/8;let C0=1;for(let oe=1;oe<4;oe++)w0.dims[oe]>1&&(C0*=w0.dims[oe]);let E0=1;for(let oe=4;oe<7;oe++)w0.dims[oe]>1&&(E0*=w0.dims[oe]);const M0=Math.max(Math.min(W,E0),1),N0=w0.vox_offset+M0*C0*x0;if(Z.byteLength<N0&&(f=await this.fetchPartial(u,N0,g),Z=await f.arrayBuffer(),h0)){let oe=new Uint8Array(Z);new Decompress$1(Le=>{oe=Le}).push(oe),Z=oe.buffer}Z.byteLength<N0?Z=null:Z=Z.slice(0,N0)}}if(!Z)if(z)Z=await NVImage.fetchDicomData(u,g),s0=NVIMAGE_TYPE.DCM_MANIFEST;else{const f=await fetch(u,{headers:g});if(!f.ok)throw Error(f.statusText);Z=await f.arrayBuffer()}const X=/(?:\.([^.]+))?$/;let r0="";v===""?r0=X.exec(u)[1]:r0=X.exec(v)[1],r0.toUpperCase()==="HEAD"&&h===""&&(h=u.substring(0,u.lastIndexOf("HEAD"))+"BRIK");let l0;if(v===""){try{l0=new URL(u).pathname.split("/")}catch{l0=u.split("/")}v=l0.slice(-1)[0],v.indexOf("?")>-1&&(v=v.slice(0,v.indexOf("?")))}let j=null;if(h.length>0){let f=await fetch(h,{headers:g});f.status===404&&h.lastIndexOf("BRIK")!==-1&&(f=await fetch(h+".gz",{headers:g})),j=await f.arrayBuffer()}if(!Z)throw new Error("Unable to load buffer properly from volume");return D=new NVImage(Z,v,w,C,j,k,U,N,O,d,M,e,b,s0),D.url=u,D.colorbarVisible=K,D}static readFileAsync(u,h=NaN){return new Promise((g,v)=>{const w=new FileReader;w.onload=()=>{u.name.lastIndexOf("gz")!==-1&&isNaN(h)?g(nifti.decompress(w.result)):g(w.result)},w.onerror=v,isNaN(h)?w.readAsArrayBuffer(u):w.readAsArrayBuffer(u.slice(0,h))})}static async loadFromFile({file:u,name:h="",colormap:g="gray",opacity:v=1,urlImgData:w=null,cal_min:C=NaN,cal_max:k=NaN,trustCalMinMax:U=!0,percentileFrac:N=.02,ignoreZeroVoxels:O=!1,useQFormNotSForm:d=!1,colormapNegative:M="",frame4D:e=0,limitFrames4D:b=NaN,imageType:z=NVIMAGE_TYPE.UNKNOWN}){let W=null,s0=[];try{if(Array.isArray(u))for(let J=0;J<u.length;J++)s0.push(await this.readFileAsync(u[J]));else{if(isNaN(b))s0=await this.readFileAsync(u,b);else{s0=await this.readFileAsync(u,512);let J=new Uint8Array(s0),D=!1;J[0]===31&&J[1]===139&&(D=!0,new Decompress$1(r0=>{J=r0}).push(J),s0=J.buffer);let Z=J[0]===92&&J[1]===1;if(Z||(Z=J[1]===92&&J[0]===1),!Z)s0=await this.readFileAsync(u);else{const X=nifti.readHeader(s0);if(!X)throw new Error("could not read nifti header");const r0=X.numBitsPerVoxel/8;let l0=1;for(let h0=1;h0<4;h0++)X.dims[h0]>1&&(l0*=X.dims[h0]);let j=1;for(let h0=4;h0<7;h0++)X.dims[h0]>1&&(j*=X.dims[h0]);const f=Math.max(Math.min(b,j),1),c0=X.vox_offset+f*l0*r0;if(s0.byteLength<c0&&(s0=await this.readFileAsync(u,c0),D)){let h0=new Uint8Array(s0);new Decompress$1(w0=>{h0=w0}).push(h0),s0=h0.buffer}if(s0.byteLength<c0)throw new Error("failed to load image data (e.g. incompressible data)");s0=s0.slice(0,c0)}}h=u.name}let K=null;w&&(K=await this.readFileAsync(w)),W=new NVImage(s0,h,g,v,K,C,k,U,N,O,d,M,e,z),W.fileObject=u}catch(K){log.error(K),log.error(K)}if(W===null)throw new Error("could not build NVImage");return W}static createNiftiArray(u=[256,256,256],h=[1,1,1],g=[1,0,0,-128,0,1,0,-128,0,0,1,-128,0,0,0,1],v=2,w=new Uint8Array){const C=this.createNiftiHeader(u,h,g,v),k=hdrToArrayBuffer(C,!1);if(w.length<1)return k;const U=new Uint8Array(4),N=new Uint8Array(w.buffer),O=new Uint8Array(k.length+U.length+N.length);return O.set(k),O.set(U,k.length),O.set(N,k.length+U.length),O}static createNiftiHeader(u=[256,256,256],h=[1,1,1],g=[1,0,0,-128,0,1,0,-128,0,0,1,-128,0,0,0,1],v=2){const w=new nifti.NIFTI1;w.littleEndian=!0,w.dims=[3,1,1,1,0,0,0,0],w.dims[0]=Math.max(3,u.length);for(let k=0;k<u.length;k++)w.dims[k+1]=u[k];w.pixDims=[1,1,1,1,1,0,0,0];for(let k=0;k<u.length;k++)w.pixDims[k+1]=h[k];if(g.length===16){let k=0;for(let U=0;U<4;U++)for(let N=0;N<4;N++)w.affine[U][N]=g[k],k++}let C=8;return v===256||v===2?C=8:v===512||v===4?C=16:v===16||v===768||v===8?C=32:v===64?C=64:log.warn("Unsupported NIfTI datatypeCode: "+v),w.datatypeCode=v,w.numBitsPerVoxel=C,w.scl_inter=0,w.scl_slope=0,w.sform_code=2,w.magic="n+1",w.vox_offset=352,w}getVolumeData(u=[-1,0,0],h=[0,0,0],g="same"){let v=new Uint8Array;if(Math.min(...u)<0||Math.min(...h)<0)return[v,[0,0,0]];const w=this.dimsRAS.slice(1,4);for(let M=0;M<3;M++)if(u[M]=Math.min(u[M],w[M]-1),h[M]=Math.min(h[M],w[M]-1),h[M]<u[M]){const e=h[M];h[M]=u[M],u[M]=e}const C=[h[0]-u[0]+1,h[1]-u[1]+1,h[2]-u[2]+1],k=C[0]*C[1]*C[2];let U=this.hdr.datatypeCode;if(g==="uint8"?U=NiiDataType.DT_UINT8:g==="float32"&&(U=NiiDataType.DT_FLOAT32),U===NiiDataType.DT_UINT8)v=new Uint8Array(k);else if(U===NiiDataType.DT_INT16)v=new Int16Array(k);else if(U===NiiDataType.DT_UINT16)v=new Uint16Array(k);else if(U===NiiDataType.DT_FLOAT32)v=new Float32Array(k);else if(U===NiiDataType.DT_FLOAT64)v=new Float64Array(k);else return log.error("getVolumeData unsupported datatype"),[v,[0,0,0]];const N=this.img2RASstep,O=this.img2RASstart;let d=0;for(let M=u[2];M<=h[2];M++){const e=O[2]+M*N[2];for(let b=u[1];b<=h[1];b++){const z=e+O[1]+b*N[1];for(let W=u[0];W<=h[0];W++){const s0=O[0]+W*N[0];v[d++]=this.img[s0+z]}}}return[v,C]}setVolumeData(u=[-1,0,0],h=[0,0,0],g=new Uint8Array){if(g.length<1||Math.min(...u)<0||Math.min(...h)<0)return;const v=this.dimsRAS.slice(1,4);for(let O=0;O<3;O++)if(u[O]=Math.min(u[O],v[O]-1),h[O]=Math.min(h[O],v[O]-1),h[O]<u[O]){const d=h[O];h[O]=u[O],u[O]=d}const w=[h[0]-u[0]+1,h[1]-u[1]+1,h[2]-u[2]+1],C=w[0]*w[1]*w[2];if(g.length<C){log.error("setVolumeData image does not have enough voxels");return}const k=this.img2RASstep,U=this.img2RASstart;let N=0;for(let O=u[2];O<=h[2];O++){const d=U[2]+O*k[2];for(let M=u[1];M<=h[1];M++){const e=d+U[1]+M*k[1];for(let b=u[0];b<=h[0];b++){const z=U[0]+b*k[0];this.img[z+e]=g[N++]}}}}static loadFromBase64({base64:u,name:h="",colormap:g="gray",opacity:v=1,cal_min:w=NaN,cal_max:C=NaN,trustCalMinMax:k=!0,percentileFrac:U=.02,ignoreZeroVoxels:N=!1,useQFormNotSForm:O=!1,colormapNegative:d="",frame4D:M=0,imageType:e=NVIMAGE_TYPE.UNKNOWN,cal_minNeg:b=NaN,cal_maxNeg:z=NaN,colorbarVisible:W=!0,colormapLabel:s0=null}){function K(D){const Z=window.atob(D),X=Z.length,r0=new Uint8Array(X);for(let l0=0;l0<X;l0++)r0[l0]=Z.charCodeAt(l0);return r0.buffer}let J=null;try{const D=K(u),Z=null;J=new NVImage(D,h,g,v,Z,w,C,k,U,N,O,d,M,e,b,z,W,s0)}catch(D){log.debug(D)}if(J===null)throw new Error("could not load NVImage");return J}clone(){const u=new NVImage;return u.id=v4(),u.hdr=Object.assign({},this.hdr),u.img=this.img.slice(),u.calculateRAS(),u.calMinMax(),u}zeroImage(){this.img.fill(0)}getImageMetadata(){if(!this.hdr)throw new Error("hdr undefined");const u=this.id,h=this.hdr.datatypeCode,g=this.hdr.dims,v=g[1],w=g[2],C=g[3],k=Math.max(1,g[4]),U=this.hdr.pixDims,N=U[1],O=U[2],d=U[3],M=U[4],e=Math.floor(this.hdr.numBitsPerVoxel/8);return{id:u,datatypeCode:h,nx:v,ny:w,nz:C,nt:k,dx:N,dy:O,dz:d,dt:M,bpv:e}}static zerosLike(u,h="same"){const g=u.clone();return g.zeroImage(),h==="uint8"&&(g.img=Uint8Array.from(g.img),g.hdr.datatypeCode=NiiDataType.DT_UINT8,g.hdr.numBitsPerVoxel=8),h==="float32"&&(g.img=Float32Array.from(g.img),g.hdr.datatypeCode=NiiDataType.DT_FLOAT32,g.hdr.numBitsPerVoxel=32),g}getValue(u,h,g,v=0,w=!1){if(!this.hdr)throw new Error("hdr undefined");if(!this.img)throw new Error("img undefined");const C=this.hdr.dims[1],k=this.hdr.dims[2],U=this.hdr.dims[3],N=this.permRAS.slice();if(N[0]!==1||N[1]!==2||N[2]!==3){const e=fromValues$1(u,h,g,1);transformMat4(e,e,this.toRASvox),u=e[0],h=e[1],g=e[2]}let O=u+h*C+g*C*k;if(this.hdr.datatypeCode===NiiDataType.DT_RGBA32)return O*=4,Math.round(this.img[O]*.21+this.img[O+1]*.72+this.img[O+2]*.07);if(this.hdr.datatypeCode===NiiDataType.DT_RGB24)return O*=3,Math.round(this.img[O]*.21+this.img[O+1]*.72+this.img[O+2]*.07);const d=v*C*k*U;let M=this.img[O+d];return w&&(M=this.imaginary[O+d]),this.hdr.scl_slope*M+this.hdr.scl_inter}toNiivueObject3D(u,h){const g=this.dimsRAS,v=this.matRAS,w=this.pixDimsRAS,C=-.5,k=-.5,U=-.5,N=g[1]-1+.5,O=g[2]-1+.5,d=g[3]-1+.5,M=this.vox2mm([C,k,U],v),e=this.vox2mm([C,O,U],v),b=this.vox2mm([C,k,d],v),z=this.vox2mm([C,O,d],v),W=this.vox2mm([N,k,U],v),s0=this.vox2mm([N,O,U],v),K=this.vox2mm([N,k,d],v),J=this.vox2mm([N,O,d],v),D=[...b,0,0,1,...K,1,0,1,...J,1,1,1,...z,0,1,1,...M,0,0,0,...e,0,1,0,...s0,1,1,0,...W,1,0,0],Z=h.createBuffer();h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,Z);const X=[0,3,2,2,1,0,4,7,6,6,5,4,5,6,2,2,3,5,4,0,1,1,7,4,7,1,2,2,6,7,4,5,3,3,0,4];h.bufferData(h.ELEMENT_ARRAY_BUFFER,new Uint16Array(X),h.STATIC_DRAW);const r0=h.createBuffer();h.bindBuffer(h.ARRAY_BUFFER,r0),h.bufferData(h.ARRAY_BUFFER,new Float32Array(D),h.STATIC_DRAW);const l0=h.createVertexArray();h.bindVertexArray(l0),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,Z),h.bindBuffer(h.ARRAY_BUFFER,r0),h.enableVertexAttribArray(0),h.vertexAttribPointer(0,3,h.FLOAT,!1,24,0),h.enableVertexAttribArray(1),h.vertexAttribPointer(1,3,h.FLOAT,!1,24,12),h.bindVertexArray(null);const j=new NiivueObject3D(u,r0,h.TRIANGLES,X.length,Z,l0),f=getExtents([...b,...K,...J,...z,...M,...e,...s0,...W]);return j.extentsMin=f.min.slice(),j.extentsMax=f.max.slice(),j.furthestVertexFromOrigin=f.furthestVertexFromOrigin,j.originNegate=clone$1(f.origin),negate(j.originNegate,j.originNegate),j.fieldOfViewDeObliqueMM=[g[1]*w[1],g[2]*w[2],g[3]*w[3]],j}applyOptionsUpdate(u){this.hdr.cal_min=u.cal_min,this.hdr.cal_max=u.cal_max,Object.assign(this,u)}getImageOptions(){return NVImageFromUrlOptions("","",this.name,this._colormap,this.opacity,this.hdr.cal_min,this.hdr.cal_max,this.trustCalMinMax,this.percentileFrac,this.ignoreZeroVoxels,this.useQFormNotSForm,this.colormapNegative,this.frame4D,this.imageType)}toUint8Array(u=null){const h=u!==null,g=hdrToArrayBuffer({...this.hdr,vox_offset:352},h);let v=u;if(h){const U=this.permRAS;if(U[0]!==1||U[1]!==2||U[2]!==3){const N=this.hdr.dims,O=[0,0,0];for(let D=0;D<3;D++)for(let Z=0;Z<3;Z++)Math.abs(U[D])-1===Z&&(O[Z]=D*Math.sign(U[D]));let d=1;const M=[1,1,1],e=[!1,!1,!1];for(let D=0;D<O.length;D++)for(let Z=0;Z<O.length;Z++)Math.abs(O[Z])===D&&(M[Z]=d,(O[Z]<0||Object.is(O[Z],-0))&&(e[Z]=!0),d*=N[Z+1]);let b=NVUtilities.range(0,N[1]-1,1);e[0]&&(b=NVUtilities.range(N[1]-1,0,-1));for(let D=0;D<N[1];D++)b[D]*=M[0];let z=NVUtilities.range(0,N[2]-1,1);e[1]&&(z=NVUtilities.range(N[2]-1,0,-1));for(let D=0;D<N[2];D++)z[D]*=M[1];let W=NVUtilities.range(0,N[3]-1,1);e[2]&&(W=NVUtilities.range(N[3]-1,0,-1));for(let D=0;D<N[3];D++)W[D]*=M[2];const s0=new Uint8Array(u),K=new Uint8Array(N[1]*N[2]*N[3]);let J=0;for(let D=0;D<N[3];D++)for(let Z=0;Z<N[2];Z++)for(let X=0;X<N[1];X++)K[J]=s0[b[X]+z[Z]+W[D]],J++;v=K,log.debug("drawing bytes"),log.debug(v)}}const w=h?v:new Uint8Array(this.img.buffer),C=new Uint8Array(4),k=new Uint8Array(g.length+C.length+w.length);return k.set(g),k.set(C,g.length),k.set(w,g.length+C.length),k}convertVox2Frac(u){return fromValues$2((u[0]+.5)/this.dimsRAS[1],(u[1]+.5)/this.dimsRAS[2],(u[2]+.5)/this.dimsRAS[3])}convertFrac2Vox(u){return fromValues$2(Math.round(u[0]*this.dims[1]-.5),Math.round(u[1]*this.dims[2]-.5),Math.round(u[2]*this.dims[3]-.5))}convertFrac2MM(u,h=!1){const g=fromValues$1(u[0],u[1],u[2],1);return h?transformMat4(g,g,this.frac2mm):transformMat4(g,g,this.frac2mmOrtho),g}convertMM2Frac(u,h=!1){const g=fromValues$1(u[0],u[1],u[2],1),v=this.dimsRAS,w=fromValues$2(0,0,0);if(typeof v>"u")return w;if(!h){const k=clone$2(this.frac2mmOrtho);return invert(k,k),transformMat4(g,g,k),w[0]=g[0],w[1]=g[1],w[2]=g[2],w}if(v[1]<1||v[2]<1||v[3]<1)return w;const C=clone$2(this.matRAS);return invert(C,C),transpose(C,C),transformMat4(g,g,C),w[0]=(g[0]+.5)/v[1],w[1]=(g[1]+.5)/v[2],w[2]=(g[2]+.5)/v[3],w}}var SLICE_TYPE=(T=>(T[T.AXIAL=0]="AXIAL",T[T.CORONAL=1]="CORONAL",T[T.SAGITTAL=2]="SAGITTAL",T[T.MULTIPLANAR=3]="MULTIPLANAR",T[T.RENDER=4]="RENDER",T))(SLICE_TYPE||{}),MULTIPLANAR_TYPE=(T=>(T[T.AUTO=0]="AUTO",T[T.COLUMN=1]="COLUMN",T[T.GRID=2]="GRID",T[T.ROW=3]="ROW",T))(MULTIPLANAR_TYPE||{}),DRAG_MODE=(T=>(T[T.none=0]="none",T[T.contrast=1]="contrast",T[T.measurement=2]="measurement",T[T.pan=3]="pan",T[T.slicer3D=4]="slicer3D",T[T.callbackOnly=5]="callbackOnly",T))(DRAG_MODE||{});const DEFAULT_OPTIONS={textHeight:.06,colorbarHeight:.05,crosshairWidth:1,crosshairGap:0,rulerWidth:4,show3Dcrosshair:!1,backColor:[0,0,0,1],crosshairColor:[1,0,0,1],fontColor:[.5,.5,.5,1],selectionBoxColor:[1,1,1,.5],clipPlaneColor:[.7,0,.7,.5],rulerColor:[1,0,0,.8],colorbarMargin:.05,trustCalMinMax:!0,clipPlaneHotKey:"KeyC",viewModeHotKey:"KeyV",doubleTouchTimeout:500,longTouchTimeout:1e3,keyDebounceTime:50,isNearestInterpolation:!1,isResizeCanvas:!0,atlasOutline:0,isRuler:!1,isColorbar:!1,isOrientCube:!1,multiplanarPadPixels:0,multiplanarForceRender:!1,isRadiologicalConvention:!1,meshThicknessOn2D:1/0,dragMode:1,yoke3Dto2DZoom:!1,isDepthPickMesh:!1,isCornerOrientationText:!1,sagittalNoseLeft:!1,isSliceMM:!1,isV1SliceShader:!1,isHighResolutionCapable:!0,logLevel:"info",loadingText:"waiting for images...",isForceMouseClickToVoxelCenters:!1,dragAndDropEnabled:!0,drawingEnabled:!1,penValue:1,floodFillNeighbors:6,isFilledPen:!1,thumbnail:"",maxDrawUndoBitmaps:8,sliceType:3,meshXRay:0,isAntiAlias:null,limitFrames4D:NaN,isAdditiveBlend:!1,showLegend:!0,legendBackgroundColor:[.3,.3,.3,.5],legendTextColor:[1,1,1,1],multiplanarLayout:0,renderOverlayBlend:1,sliceMosaicString:""},INITIAL_SCENE_DATA={azimuth:110,elevation:10,crosshairPos:fromValues$2(.5,.5,.5),clipPlane:[0,0,0,0],clipPlaneDepthAziElev:[2,0,0],volScaleMultiplier:1,pan2Dxyzmm:fromValues$1(0,0,0,1)};class NVDocument{constructor(){g0(this,"data",{title:"Untitled document",imageOptionsArray:[],meshOptionsArray:[],opts:{...DEFAULT_OPTIONS},previewImageDataURL:"",labels:[],encodedImageBlobs:[],encodedDrawingBlob:""});g0(this,"scene");g0(this,"volumes",[]);g0(this,"meshDataObjects");g0(this,"meshes",[]);g0(this,"drawBitmap",null);g0(this,"imageOptionsMap",new Map);g0(this,"meshOptionsMap",new Map);this.scene={onAzimuthElevationChange:()=>{},onZoom3DChange:()=>{},sceneData:INITIAL_SCENE_DATA,get renderAzimuth(){return this.sceneData.azimuth},set renderAzimuth(u){this.sceneData.azimuth=u,this.onAzimuthElevationChange&&this.onAzimuthElevationChange(this.sceneData.azimuth,this.sceneData.elevation)},get renderElevation(){return this.sceneData.elevation},set renderElevation(u){this.sceneData.elevation=u,this.onAzimuthElevationChange&&this.onAzimuthElevationChange(this.sceneData.azimuth,this.sceneData.elevation)},get volScaleMultiplier(){return this.sceneData.volScaleMultiplier},set volScaleMultiplier(u){this.sceneData.volScaleMultiplier=u,this.onZoom3DChange(u)},get crosshairPos(){return this.sceneData.crosshairPos},set crosshairPos(u){this.sceneData.crosshairPos=u},get clipPlane(){return this.sceneData.clipPlane},set clipPlane(u){this.sceneData.clipPlane=u},get clipPlaneDepthAziElev(){return this.sceneData.clipPlaneDepthAziElev},set clipPlaneDepthAziElev(u){this.sceneData.clipPlaneDepthAziElev=u},get pan2Dxyzmm(){return this.sceneData.pan2Dxyzmm},set pan2Dxyzmm(u){this.sceneData.pan2Dxyzmm=u}}}get title(){return this.data.title}get previewImageDataURL(){return this.data.previewImageDataURL}set previewImageDataURL(u){this.data.previewImageDataURL=u}set title(u){this.data.title=u}get imageOptionsArray(){return this.data.imageOptionsArray}get encodedImageBlobs(){return this.data.encodedImageBlobs}get encodedDrawingBlob(){return this.data.encodedDrawingBlob}get opts(){return this.data.opts}set opts(u){this.data.opts={...u}}get labels(){return this.data.labels}set labels(u){this.data.labels=u}get customData(){return this.data.customData}set customData(u){this.data.customData=u}hasImage(u){return this.volumes.find(h=>h.id===u.id)!==void 0}hasImageFromUrl(u){return this.data.imageOptionsArray.find(h=>h.url===u)!==void 0}addImageOptions(u,h){if(!this.hasImage(u)&&!h.name)if(h.url){const v=/^(?:[a-z+]+:)?\/\//i.test(h.url)?new URL(h.url):new URL(h.url,window.location.href);h.name=v.pathname.split("/").pop(),h.name.toLowerCase().endsWith(".gz")&&(h.name=h.name.slice(0,-3)),h.name.toLowerCase().endsWith(".nii")||(h.name+=".nii")}else h.name="untitled.nii";h.imageType=NVIMAGE_TYPE.NII,this.data.imageOptionsArray.push(h),this.imageOptionsMap.set(u.id,this.data.imageOptionsArray.length-1)}removeImage(u){if(this.imageOptionsMap.has(u.id)){const h=this.imageOptionsMap.get(u.id);this.data.imageOptionsArray.length>h&&this.data.imageOptionsArray.splice(h,1),this.imageOptionsMap.delete(u.id)}this.volumes=this.volumes.filter(h=>h.id!==u.id)}getImageOptions(u){return this.imageOptionsMap.has(u.id)?this.data.imageOptionsArray[this.imageOptionsMap.get(u.id)]:null}json(){const u={encodedImageBlobs:[],previewImageDataURL:this.data.previewImageDataURL,imageOptionsMap:new Map},h=[];if(u.sceneData={...this.scene.sceneData},u.opts={...this.opts},this.opts.meshThicknessOn2D===1/0&&(u.opts.meshThicknessOn2D="infinity"),u.labels=[...this.data.labels],u.customData=this.customData,this.volumes.length){let v=this.imageOptionsArray[0];if(v||(log.debug("no image options for base image"),v={name:"",colormap:"gray",opacity:1,pairedImgData:null,cal_min:NaN,cal_max:NaN,trustCalMinMax:!0,percentileFrac:.02,ignoreZeroVoxels:!1,useQFormNotSForm:!1,colormapNegative:"",colormapLabel:null,imageType:NVIMAGE_TYPE.NII,frame4D:0,limitFrames4D:NaN,url:"",urlImageData:"",alphaThreshold:!1,cal_minNeg:NaN,cal_maxNeg:NaN,colorbarVisible:!0}),v.colormap=this.volumes[0].colormap,v.opacity=this.volumes[0].opacity,v.cal_max=this.volumes[0].cal_max||NaN,v.cal_min=this.volumes[0].cal_min||NaN,v){h.push(v);const w=NVUtilities.uint8tob64(this.volumes[0].toUint8Array());u.encodedImageBlobs.push(w),this.drawBitmap&&(u.encodedDrawingBlob=NVUtilities.uint8tob64(this.volumes[0].toUint8Array(this.drawBitmap))),u.imageOptionsMap.set(this.volumes[0].id,0)}else throw new Error("image options for base layer not found");for(let w=1;w<this.volumes.length;w++){const C=this.volumes[w];let k=this.getImageOptions(C);k===null?(log.warn("no options found for image, using default"),k={name:"",colormap:"gray",opacity:1,pairedImgData:null,cal_min:NaN,cal_max:NaN,trustCalMinMax:!0,percentileFrac:.02,ignoreZeroVoxels:!1,useQFormNotSForm:!1,colormapNegative:"",colormapLabel:null,imageType:NVIMAGE_TYPE.NII,frame4D:0,limitFrames4D:NaN,url:"",urlImageData:"",alphaThreshold:!1,cal_minNeg:NaN,cal_maxNeg:NaN,colorbarVisible:!0}):"imageType"in k||(k.imageType=NVIMAGE_TYPE.NII),k.colormap=C.colormap,k.colormapLabel=C.colormapLabel,k.opacity=C.opacity,k.cal_max=C.cal_max||NaN,k.cal_min=C.cal_min||NaN,h.push(k);const U=NVUtilities.uint8tob64(C.toUint8Array());u.encodedImageBlobs.push(U),u.imageOptionsMap.set(C.id,w)}}u.imageOptionsArray=[...h];const g=[];u.connectomes=[];for(const v of this.meshes){if(v.type===MeshType.CONNECTOME){u.connectomes.push(JSON.stringify(v.json()));continue}const w={pts:v.pts,tris:v.tris,name:v.name,rgba255:Uint8Array.from(v.rgba255),opacity:v.opacity,connectome:v.connectome,dpg:v.dpg,dps:v.dps,dpv:v.dpv,meshShaderIndex:v.meshShaderIndex,layers:v.layers.map(C=>({values:C.values,nFrame4D:C.nFrame4D,frame4D:0,outlineBorder:C.outlineBorder,global_min:C.global_min,global_max:C.global_max,cal_min:C.cal_min,cal_max:C.cal_max,opacity:C.opacity,colormap:C.colormap,colormapNegative:C.colormapNegative,colormapLabel:C.colormapLabel,useNegativeCmap:C.useNegativeCmap})),hasConnectome:v.hasConnectome,edgeColormap:v.edgeColormap,edgeColormapNegative:v.edgeColormapNegative,edgeMax:v.edgeMax,edgeMin:v.edgeMin,edges:v.edges&&Array.isArray(v.edges)?[...v.edges]:[],extentsMax:v.extentsMax,extentsMin:v.extentsMin,fiberGroupColormap:v.fiberGroupColormap,furthestVertexFromOrigin:v.furthestVertexFromOrigin,nodeColormap:v.nodeColormap,nodeColormapNegative:v.nodeColormapNegative,nodeMaxColor:v.nodeMaxColor,nodeMinColor:v.nodeMinColor,nodeScale:v.nodeScale,legendLineThickness:v.legendLineThickness,offsetPt0:v.offsetPt0,nodes:v.nodes};g.push(w)}return u.meshesString=JSON.stringify(serialize(g)),u}download(u){const h=this.json();NVUtilities.download(JSON.stringify(h),u,"application/json")}static deserializeMeshDataObjects(u){if(u.data.meshesString){u.meshDataObjects=deserialize(JSON.parse(u.data.meshesString));for(const h of u.meshDataObjects)for(const g of h.layers)"colorMap"in g&&(g.colormap=g.colorMap,delete g.colorMap),"colorMapNegative"in g&&(g.colormapNegative=g.colorMapNegative,delete g.colorMapNegative)}}static async loadFromUrl(u){const g=await(await fetch(u)).json();return NVDocument.loadFromJSON(g)}static async loadFromFile(u){const h=await NVUtilities.readFileAsync(u),g=new NVDocument,w=new TextDecoder().decode(h);return g.data=JSON.parse(w),g.data.opts.meshThicknessOn2D==="infinity"&&(g.data.opts.meshThicknessOn2D=1/0),g.scene.sceneData={...INITIAL_SCENE_DATA,...g.data.sceneData},NVDocument.deserializeMeshDataObjects(g),g}static loadFromJSON(u){const h=new NVDocument;return h.data=u,h.data.opts.meshThicknessOn2D==="infinity"&&(h.data.opts.meshThicknessOn2D=1/0),h.scene.sceneData={...INITIAL_SCENE_DATA,...u.sceneData},NVDocument.deserializeMeshDataObjects(h),h}}var LabelTextAlignment=(T=>(T.LEFT="left",T.RIGHT="right",T.CENTER="center",T))(LabelTextAlignment||{}),LabelLineTerminator=(T=>(T.NONE="none",T.CIRCLE="circle",T.RING="ring",T))(LabelLineTerminator||{});class NVLabel3DStyle{constructor(u=[1,1,1,1],h=1,g="left",v=0,w=[0,0,0],C="none",k,U,N){g0(this,"textColor");g0(this,"textScale");g0(this,"textAlignment");g0(this,"lineWidth");g0(this,"lineColor");g0(this,"lineTerminator");g0(this,"bulletScale");g0(this,"bulletColor");g0(this,"backgroundColor");this.textColor=u,this.textScale=h,this.textAlignment=g,this.lineWidth=v,this.lineColor=w,this.lineTerminator=C,this.bulletScale=k,this.bulletColor=U,this.backgroundColor=N}}class NVLabel3D{constructor(u,h,g){g0(this,"text");g0(this,"style");g0(this,"points");this.text=u,this.style=h,this.points=g}}const defaultOptions={name:"untitled connectome",nodeColormap:"warm",nodeColormapNegative:"winter",nodeMinColor:0,nodeMaxColor:4,nodeScale:3,edgeColormap:"warm",edgeColormapNegative:"winter",edgeMin:2,edgeMax:6,edgeScale:1,legendLineThickness:0};class NVConnectome extends NVMesh{constructor(h,g){super(new Float32Array([]),new Uint32Array([]),g.name,new Uint8Array([]),1,!0,h,g);g0(this,"gl");g0(this,"nodesChanged");this.gl=h,this.type=MeshType.CONNECTOME,this.nodes&&this.updateLabels(),this.nodesChanged=new EventTarget}static convertLegacyConnectome(h){const g={nodes:[],edges:[],...defaultOptions};for(const w in h)if(w in defaultOptions){const C=w;g[C]=h[C]}const v=h.nodes;for(let w=0;w<v.names.length;w++)g.nodes.push({name:v.names[w],x:v.X[w],y:v.Y[w],z:v.Z[w],colorValue:v.Color[w],sizeValue:v.Size[w]});for(let w=0;w<v.names.length-1;w++)for(let C=w+1;C<v.names.length;C++){const k=h.edges[w*v.names.length+C];g.edges.push({first:w,second:C,colorValue:k})}return g}static convertFreeSurferConnectome(h,g="warm"){let v=!0;if("data_type"in h?h.data_type!=="fs_pointset"&&(v=!1):v=!1,"points"in h||(v=!1),!v)throw Error("not a valid FreeSurfer json pointset");const w=h.points.map(k=>({name:Array.isArray(k.comments)&&k.comments.length>0&&"text"in k.comments[0]?k.comments[0].text:"",x:k.coordinates.x,y:k.coordinates.y,z:k.coordinates.z,colorValue:1,sizeValue:1,metadata:k.comments}));return{...defaultOptions,nodeColormap:g,edgeColormap:g,nodes:w,edges:[]}}updateLabels(){const h=this.nodes;if(h&&h.length>0){const g=h.reduce((O,d)=>O.sizeValue>d.sizeValue?O:d).sizeValue,v=this.nodeMinColor?this.nodeMinColor:h.reduce((O,d)=>O.colorValue<d.colorValue?O:d).colorValue,w=this.nodeMaxColor?this.nodeMaxColor:h.reduce((O,d)=>O.colorValue>d.colorValue?O:d).colorValue,C=cmapper.colormap(this.nodeColormap,this.colormapInvert),k=cmapper.colormap(this.nodeColormapNegative,this.colormapInvert),U="nodeColormapNegative"in this,N=this.legendLineThickness?this.legendLineThickness:0;for(let O=0;O<h.length;O++){let d=h[O].colorValue,M=!1;if(U&&d<0&&(M=!0,d=-d),v<w){if(d<v){log.warn("color value lower than min");continue}d=(d-v)/(w-v)}else d=1;d=Math.round(Math.max(Math.min(255,d*255)))*4;let e=[C[d],C[d+1],C[d+2],255];M&&(e=[k[d],k[d+1],k[d+2],255]),e=e.map(b=>b/255),log.debug("adding label for ",h[O]),h[O].label=new NVLabel3D(h[O].name,{textColor:e,bulletScale:h[O].sizeValue/g,bulletColor:e,lineWidth:N,lineColor:e,textScale:1,textAlignment:LabelTextAlignment.LEFT,lineTerminator:LabelLineTerminator.NONE},[h[O].x,h[O].y,h[O].z]),log.debug("label for node:",h[O].label)}}}addConnectomeNode(h){if(log.debug("adding node",h),!this.nodes)throw new Error("nodes not defined");this.nodes.push(h),this.updateLabels(),this.nodesChanged.dispatchEvent(new CustomEvent("nodeAdded",{detail:{node:h}}))}deleteConnectomeNode(h){const g=this.nodes.indexOf(h),v=this.edges;v&&(this.edges=v.filter(w=>w.first!==g&&w.second!==g)),this.nodes=this.nodes.filter(w=>w!==h),this.updateLabels(),this.updateConnectome(this.gl),this.nodesChanged.dispatchEvent(new CustomEvent("nodeDeleted",{detail:{node:h}}))}updateConnectomeNodeByIndex(h,g){this.nodes[h]=g,this.updateLabels(),this.updateConnectome(this.gl),this.nodesChanged.dispatchEvent(new CustomEvent("nodeChanged",{detail:{node:g}}))}updateConnectomeNodeByPoint(h,g){const v=this.nodes;if(!v)throw new Error("Node to update does not exist");const w=v.find(k=>NVUtilities.arraysAreEqual([k.x,k.y,k.z],h));if(!w)throw new Error(`Node with point ${h} to update does not exist`);const C=v.findIndex(k=>k===w);this.updateConnectomeNodeByIndex(C,g)}addConnectomeEdge(h,g,v){const w=this.edges;let C=w.find(k=>(k.first===h||k.second===h)&&k.first+k.second===h+g);return C||(C={first:h,second:g,colorValue:v},w.push(C),this.updateConnectome(this.gl),C)}deleteConnectomeEdge(h,g){const v=this.edges,w=v.find(C=>(C.first===h||C.first===g)&&C.first+C.second===h+g);if(w)this.edges=v.filter(C=>C!==w);else throw new Error(`edge between ${h} and ${g} not found`);return this.updateConnectome(this.gl),w}findClosestConnectomeNode(h,g){const v=this.nodes;if(!v||v.length===0)return null;const w=v.map((C,k)=>({node:C,distance:Math.sqrt(Math.pow(C.x-h[0],2)+Math.pow(C.y-h[1],2)+Math.pow(C.z-h[2],2)),index:k})).filter(C=>C.distance<g).sort((C,k)=>C.distance-k.distance);return w.length>0?w[0].node:null}updateConnectome(h){const g=[],v=[],w=[];let C=cmapper.colormap(this.nodeColormap,this.colormapInvert),k=cmapper.colormap(this.nodeColormapNegative,this.colormapInvert),U="nodeColormapNegative"in this;if(this.nodeMinColor===void 0||this.nodeMaxColor===void 0)throw new Error("nodeMinColor or nodeMaxColor is undefined");if(this.edgeMin===void 0||this.edgeMax===void 0)throw new Error("edgeMin or edgeMax undefined");let N=this.nodeMinColor,O=this.nodeMaxColor;const d=this.nodes,M=d.length;for(let K=0;K<M;K++){const J=d[K].sizeValue*this.nodeScale;if(J<=0)continue;let D=d[K].colorValue,Z=!1;if(U&&D<0&&(Z=!0,D=-D),N<O){if(D<N)continue;D=(D-N)/(O-N)}else D=1;D=Math.round(Math.max(Math.min(255,D*255)))*4;let X=[C[D],C[D+1],C[D+2],255];Z&&(X=[k[D],k[D+1],k[D+2],255]);const r0=fromValues$2(d[K].x,d[K].y,d[K].z);NiivueObject3D.makeColoredSphere(v,g,w,J,r0,X)}C=cmapper.colormap(this.edgeColormap,this.colormapInvert),k=cmapper.colormap(this.edgeColormapNegative,this.colormapInvert),U="edgeColormapNegative"in this,N=this.edgeMin,O=this.edgeMax;const e=this.edges;for(const K of e){let J=K.colorValue;const D=U&&J<0;D&&(J=-J);const Z=J*this.edgeScale;if(Z<=0)continue;if(N<O){if(J<N)continue;J=(J-N)/(O-N)}else J=1;J=Math.round(Math.max(Math.min(255,J*255)))*4;let X=[C[J],C[J+1],C[J+2],255];D&&(X=[k[J],k[J+1],k[J+2],255]);const r0=fromValues$2(d[K.first].x,d[K.first].y,d[K.first].z),l0=fromValues$2(d[K.second].x,d[K.second].y,d[K.second].z);NiivueObject3D.makeColoredCylinder(v,g,w,r0,l0,Z,X)}const b=new Float32Array(v),z=new Uint32Array(g),W=NVMeshUtilities.getExtents(b);this.furthestVertexFromOrigin=W.mxDx,this.extentsMin=W.extentsMin,this.extentsMax=W.extentsMax;const s0=this.generatePosNormClr(b,z,new Uint8Array(w));h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),h.bufferData(h.ELEMENT_ARRAY_BUFFER,Uint32Array.from(z),h.STATIC_DRAW),h.bindBuffer(h.ARRAY_BUFFER,this.vertexBuffer),h.bufferData(h.ARRAY_BUFFER,Float32Array.from(s0),h.STATIC_DRAW),this.indexCount=g.length}updateMesh(h){this.updateConnectome(h),this.updateLabels()}json(){const h={};for(const g in this)(g in defaultOptions||g==="nodes"||g==="edges")&&(h[g]=this[g]);return h}static async loadConnectomeFromUrl(h,g){const w=await(await fetch(g)).json();return new NVConnectome(h,w)}}function img2ras16(T){const u=T.hdr.dims,h=T.permRAS,g=u[1]*u[2]*u[3],v=new Int16Array(g),w=[0,0,0];for(let e=0;e<3;e++)for(let b=0;b<3;b++)Math.abs(h[e])-1===b&&(w[b]=e*Math.sign(h[e]));let C=1;const k=[1,1,1],U=[!1,!1,!1];for(let e=0;e<w.length;e++)for(let b=0;b<w.length;b++)Math.abs(w[b])===e&&(k[b]=C,(w[b]<0||Object.is(w[b],-0))&&(U[b]=!0),C*=u[b+1]);let N=NVUtilities.range(0,u[1]-1,1);U[0]&&(N=NVUtilities.range(u[1]-1,0,-1));for(let e=0;e<u[1];e++)N[e]*=k[0];let O=NVUtilities.range(0,u[2]-1,1);U[1]&&(O=NVUtilities.range(u[2]-1,0,-1));for(let e=0;e<u[2];e++)O[e]*=k[1];let d=NVUtilities.range(0,u[3]-1,1);U[2]&&(d=NVUtilities.range(u[3]-1,0,-1));for(let e=0;e<u[3];e++)d[e]*=k[2];let M=0;for(let e=0;e<u[3];e++)for(let b=0;b<u[2];b++)for(let z=0;z<u[1];z++)v[N[z]+O[b]+d[e]]=T.img[M],M++;return v}function nice(T,u){const h=Math.floor(Math.log(T)/Math.log(10)),g=T/Math.pow(10,h);let v;return u?g<1.5?v=1:g<3?v=2:g<7?v=5:v=10:g<=1?v=1:g<=2?v=2:g<=5?v=5:v=10,v*Math.pow(10,h)}function loose_label(T,u,h=4){const g=nice(u-T,!1),v=nice(g/(h-1),!0),w=Math.floor(T/v)*v,C=Math.ceil(u/v)*v;return[v,w,C,w===T&&C===u]}function tickSpacing(T,u){let h=loose_label(T,u,3);return h[3]||(h=loose_label(T,u,5)),h[3]||(h=loose_label(T,u,4)),h[3]||(h=loose_label(T,u,3)),h[3]||(h=loose_label(T,u,5)),[h[0],h[1],h[2]]}function deg2rad(T){return T*(Math.PI/180)}function negMinMax(T,u,h,g){let v=-T,w=-u;return isFinite(h)&&isFinite(g)&&(v=h,w=g),v>w&&([v,w]=[w,v]),[v,w]}function swizzleVec3(T,u=[0,1,2]){const h=create$2();return h[0]=T[u[0]],h[1]=T[u[1]],h[2]=T[u[2]],h}function isRadiological(T){const u=fromValues$1(1,0,0,0),h=create$1();return transformMat4(h,u,T),h[0]}function unProject(T,u,h,g){const v=fromValues$1(T,u,h,1),w=clone$2(g);invert(w,w),v[0]=v[0]*2-1,v[1]=v[1]*2-1,v[2]=v[2]*2-1;const C=create$1();return transformMat4(C,v,w),C[3]===0||(C[0]/=C[3],C[1]/=C[3],C[2]/=C[3]),C}function unpackFloatFromVec4i(T){const u=[5960464477539063e-23,152587890625e-16,.00390625,1];return(T[0]*u[0]+T[1]*u[1]+T[2]*u[2]+T[3]*u[3])/255}function clamp(T,u,h){return Math.min(Math.max(T,u),h)}function encodeRLE(T){const u=T.length;let h=0;const g=new Uint8Array(u+Math.ceil(.01*u)),v=new Int8Array(g.buffer);let w=0;for(;h<u;){let C=T[h];h++;let k=1;for(;k<129&&h<u&&T[h]===C;)h++,k++;if(k>1){v[w]=-k+1,w++,g[w]=C,w++;continue}for(;h<u&&!(k>127||h+2<u&&C!==T[h]&&T[h+2]===T[h]&&T[h+1]===T[h]);)C=T[h],h++,k++;g[w]=k-1,w++;for(let U=0;U<k;U++)g[w]=T[h-k+U],w++}return log.info("PackBits "+u+" -> "+w+" bytes (x"+u/w+")"),g.slice(0,w)}function decodeRLE(T,u){const h=new Uint8Array(T.buffer),g=new Int8Array(h.buffer);let v=0;const w=new Uint8Array(u);let C=0;for(;v<h.length;){const k=g[v];if(v++,k<0){const U=g[v];v++;for(let N=0;N<1-k;N++)w[C]=U,C++}else for(let U=0;U<k+1;U++)w[C]=g[v],v++,C++}return w}function intensityRaw2Scaled(T,u){return T.scl_slope===0&&(T.scl_slope=1),u*T.scl_slope+T.scl_inter}var extendStatics=function(T,u){return extendStatics=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(h,g){h.__proto__=g}||function(h,g){for(var v in g)Object.prototype.hasOwnProperty.call(g,v)&&(h[v]=g[v])},extendStatics(T,u)};function __extends(T,u){if(typeof u!="function"&&u!==null)throw new TypeError("Class extends value "+String(u)+" is not a constructor or null");extendStatics(T,u);function h(){this.constructor=T}T.prototype=u===null?Object.create(u):(h.prototype=u.prototype,new h)}var __assign=function(){return __assign=Object.assign||function(u){for(var h,g=1,v=arguments.length;g<v;g++){h=arguments[g];for(var w in h)Object.prototype.hasOwnProperty.call(h,w)&&(u[w]=h[w])}return u},__assign.apply(this,arguments)};function __values(T){var u=typeof Symbol=="function"&&Symbol.iterator,h=u&&T[u],g=0;if(h)return h.call(T);if(T&&typeof T.length=="number")return{next:function(){return T&&g>=T.length&&(T=void 0),{value:T&&T[g++],done:!T}}};throw new TypeError(u?"Object is not iterable.":"Symbol.iterator is not defined.")}function __read(T,u){var h=typeof Symbol=="function"&&T[Symbol.iterator];if(!h)return T;var g=h.call(T),v,w=[],C;try{for(;(u===void 0||u-- >0)&&!(v=g.next()).done;)w.push(v.value)}catch(k){C={error:k}}finally{try{v&&!v.done&&(h=g.return)&&h.call(g)}finally{if(C)throw C.error}}return w}function __spreadArray(T,u,h){if(h||arguments.length===2)for(var g=0,v=u.length,w;g<v;g++)(w||!(g in u))&&(w||(w=Array.prototype.slice.call(u,0,g)),w[g]=u[g]);return T.concat(w||Array.prototype.slice.call(u))}typeof SuppressedError=="function"&&SuppressedError;function isFunction(T){return typeof T=="function"}function createErrorClass(T){var u=function(g){Error.call(g),g.stack=new Error().stack},h=T(u);return h.prototype=Object.create(Error.prototype),h.prototype.constructor=h,h}var UnsubscriptionError=createErrorClass(function(T){return function(h){T(this),this.message=h?h.length+` errors occurred during unsubscription:
1615
1615
  `+h.map(function(g,v){return v+1+") "+g.toString()}).join(`
1616
- `):"",this.name="UnsubscriptionError",this.errors=h}});function arrRemove(T,u){if(T){var h=T.indexOf(u);0<=h&&T.splice(h,1)}}var Subscription=function(){function T(u){this.initialTeardown=u,this.closed=!1,this._parentage=null,this._finalizers=null}return T.prototype.unsubscribe=function(){var u,h,g,v,w;if(!this.closed){this.closed=!0;var C=this._parentage;if(C)if(this._parentage=null,Array.isArray(C))try{for(var k=__values(C),U=k.next();!U.done;U=k.next()){var N=U.value;N.remove(this)}}catch(z){u={error:z}}finally{try{U&&!U.done&&(h=k.return)&&h.call(k)}finally{if(u)throw u.error}}else C.remove(this);var O=this.initialTeardown;if(isFunction(O))try{O()}catch(z){w=z instanceof UnsubscriptionError?z.errors:[z]}var d=this._finalizers;if(d){this._finalizers=null;try{for(var M=__values(d),e=M.next();!e.done;e=M.next()){var b=e.value;try{execFinalizer(b)}catch(z){w=w??[],z instanceof UnsubscriptionError?w=__spreadArray(__spreadArray([],__read(w)),__read(z.errors)):w.push(z)}}}catch(z){g={error:z}}finally{try{e&&!e.done&&(v=M.return)&&v.call(M)}finally{if(g)throw g.error}}}if(w)throw new UnsubscriptionError(w)}},T.prototype.add=function(u){var h;if(u&&u!==this)if(this.closed)execFinalizer(u);else{if(u instanceof T){if(u.closed||u._hasParent(this))return;u._addParent(this)}(this._finalizers=(h=this._finalizers)!==null&&h!==void 0?h:[]).push(u)}},T.prototype._hasParent=function(u){var h=this._parentage;return h===u||Array.isArray(h)&&h.includes(u)},T.prototype._addParent=function(u){var h=this._parentage;this._parentage=Array.isArray(h)?(h.push(u),h):h?[h,u]:u},T.prototype._removeParent=function(u){var h=this._parentage;h===u?this._parentage=null:Array.isArray(h)&&arrRemove(h,u)},T.prototype.remove=function(u){var h=this._finalizers;h&&arrRemove(h,u),u instanceof T&&u._removeParent(this)},T.EMPTY=function(){var u=new T;return u.closed=!0,u}(),T}(),EMPTY_SUBSCRIPTION=Subscription.EMPTY;function isSubscription(T){return T instanceof Subscription||T&&"closed"in T&&isFunction(T.remove)&&isFunction(T.add)&&isFunction(T.unsubscribe)}function execFinalizer(T){isFunction(T)?T():T.unsubscribe()}var config={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1},timeoutProvider={setTimeout:function(T,u){for(var h=[],g=2;g<arguments.length;g++)h[g-2]=arguments[g];return setTimeout.apply(void 0,__spreadArray([T,u],__read(h)))},clearTimeout:function(T){var u=timeoutProvider.delegate;return((u==null?void 0:u.clearTimeout)||clearTimeout)(T)},delegate:void 0};function reportUnhandledError(T){timeoutProvider.setTimeout(function(){throw T})}function noop(){}function errorContext(T){T()}var Subscriber=function(T){__extends(u,T);function u(h){var g=T.call(this)||this;return g.isStopped=!1,h?(g.destination=h,isSubscription(h)&&h.add(g)):g.destination=EMPTY_OBSERVER,g}return u.create=function(h,g,v){return new SafeSubscriber(h,g,v)},u.prototype.next=function(h){this.isStopped||this._next(h)},u.prototype.error=function(h){this.isStopped||(this.isStopped=!0,this._error(h))},u.prototype.complete=function(){this.isStopped||(this.isStopped=!0,this._complete())},u.prototype.unsubscribe=function(){this.closed||(this.isStopped=!0,T.prototype.unsubscribe.call(this),this.destination=null)},u.prototype._next=function(h){this.destination.next(h)},u.prototype._error=function(h){try{this.destination.error(h)}finally{this.unsubscribe()}},u.prototype._complete=function(){try{this.destination.complete()}finally{this.unsubscribe()}},u}(Subscription),_bind=Function.prototype.bind;function bind(T,u){return _bind.call(T,u)}var ConsumerObserver=function(){function T(u){this.partialObserver=u}return T.prototype.next=function(u){var h=this.partialObserver;if(h.next)try{h.next(u)}catch(g){handleUnhandledError(g)}},T.prototype.error=function(u){var h=this.partialObserver;if(h.error)try{h.error(u)}catch(g){handleUnhandledError(g)}else handleUnhandledError(u)},T.prototype.complete=function(){var u=this.partialObserver;if(u.complete)try{u.complete()}catch(h){handleUnhandledError(h)}},T}(),SafeSubscriber=function(T){__extends(u,T);function u(h,g,v){var w=T.call(this)||this,C;if(isFunction(h)||!h)C={next:h??void 0,error:g??void 0,complete:v??void 0};else{var k;w&&config.useDeprecatedNextContext?(k=Object.create(h),k.unsubscribe=function(){return w.unsubscribe()},C={next:h.next&&bind(h.next,k),error:h.error&&bind(h.error,k),complete:h.complete&&bind(h.complete,k)}):C=h}return w.destination=new ConsumerObserver(C),w}return u}(Subscriber);function handleUnhandledError(T){reportUnhandledError(T)}function defaultErrorHandler(T){throw T}var EMPTY_OBSERVER={closed:!0,next:noop,error:defaultErrorHandler,complete:noop},observable=function(){return typeof Symbol=="function"&&Symbol.observable||"@@observable"}();function identity(T){return T}function pipeFromArray(T){return T.length===0?identity:T.length===1?T[0]:function(h){return T.reduce(function(g,v){return v(g)},h)}}var Observable=function(){function T(u){u&&(this._subscribe=u)}return T.prototype.lift=function(u){var h=new T;return h.source=this,h.operator=u,h},T.prototype.subscribe=function(u,h,g){var v=this,w=isSubscriber(u)?u:new SafeSubscriber(u,h,g);return errorContext(function(){var C=v,k=C.operator,U=C.source;w.add(k?k.call(w,U):U?v._subscribe(w):v._trySubscribe(w))}),w},T.prototype._trySubscribe=function(u){try{return this._subscribe(u)}catch(h){u.error(h)}},T.prototype.forEach=function(u,h){var g=this;return h=getPromiseCtor(h),new h(function(v,w){var C=new SafeSubscriber({next:function(k){try{u(k)}catch(U){w(U),C.unsubscribe()}},error:w,complete:v});g.subscribe(C)})},T.prototype._subscribe=function(u){var h;return(h=this.source)===null||h===void 0?void 0:h.subscribe(u)},T.prototype[observable]=function(){return this},T.prototype.pipe=function(){for(var u=[],h=0;h<arguments.length;h++)u[h]=arguments[h];return pipeFromArray(u)(this)},T.prototype.toPromise=function(u){var h=this;return u=getPromiseCtor(u),new u(function(g,v){var w;h.subscribe(function(C){return w=C},function(C){return v(C)},function(){return g(w)})})},T.create=function(u){return new T(u)},T}();function getPromiseCtor(T){var u;return(u=T??config.Promise)!==null&&u!==void 0?u:Promise}function isObserver(T){return T&&isFunction(T.next)&&isFunction(T.error)&&isFunction(T.complete)}function isSubscriber(T){return T&&T instanceof Subscriber||isObserver(T)&&isSubscription(T)}var ObjectUnsubscribedError=createErrorClass(function(T){return function(){T(this),this.name="ObjectUnsubscribedError",this.message="object unsubscribed"}}),Subject=function(T){__extends(u,T);function u(){var h=T.call(this)||this;return h.closed=!1,h.currentObservers=null,h.observers=[],h.isStopped=!1,h.hasError=!1,h.thrownError=null,h}return u.prototype.lift=function(h){var g=new AnonymousSubject(this,this);return g.operator=h,g},u.prototype._throwIfClosed=function(){if(this.closed)throw new ObjectUnsubscribedError},u.prototype.next=function(h){var g=this;errorContext(function(){var v,w;if(g._throwIfClosed(),!g.isStopped){g.currentObservers||(g.currentObservers=Array.from(g.observers));try{for(var C=__values(g.currentObservers),k=C.next();!k.done;k=C.next()){var U=k.value;U.next(h)}}catch(N){v={error:N}}finally{try{k&&!k.done&&(w=C.return)&&w.call(C)}finally{if(v)throw v.error}}}})},u.prototype.error=function(h){var g=this;errorContext(function(){if(g._throwIfClosed(),!g.isStopped){g.hasError=g.isStopped=!0,g.thrownError=h;for(var v=g.observers;v.length;)v.shift().error(h)}})},u.prototype.complete=function(){var h=this;errorContext(function(){if(h._throwIfClosed(),!h.isStopped){h.isStopped=!0;for(var g=h.observers;g.length;)g.shift().complete()}})},u.prototype.unsubscribe=function(){this.isStopped=this.closed=!0,this.observers=this.currentObservers=null},Object.defineProperty(u.prototype,"observed",{get:function(){var h;return((h=this.observers)===null||h===void 0?void 0:h.length)>0},enumerable:!1,configurable:!0}),u.prototype._trySubscribe=function(h){return this._throwIfClosed(),T.prototype._trySubscribe.call(this,h)},u.prototype._subscribe=function(h){return this._throwIfClosed(),this._checkFinalizedStatuses(h),this._innerSubscribe(h)},u.prototype._innerSubscribe=function(h){var g=this,v=this,w=v.hasError,C=v.isStopped,k=v.observers;return w||C?EMPTY_SUBSCRIPTION:(this.currentObservers=null,k.push(h),new Subscription(function(){g.currentObservers=null,arrRemove(k,h)}))},u.prototype._checkFinalizedStatuses=function(h){var g=this,v=g.hasError,w=g.thrownError,C=g.isStopped;v?h.error(w):C&&h.complete()},u.prototype.asObservable=function(){var h=new Observable;return h.source=this,h},u.create=function(h,g){return new AnonymousSubject(h,g)},u}(Observable),AnonymousSubject=function(T){__extends(u,T);function u(h,g){var v=T.call(this)||this;return v.destination=h,v.source=g,v}return u.prototype.next=function(h){var g,v;(v=(g=this.destination)===null||g===void 0?void 0:g.next)===null||v===void 0||v.call(g,h)},u.prototype.error=function(h){var g,v;(v=(g=this.destination)===null||g===void 0?void 0:g.error)===null||v===void 0||v.call(g,h)},u.prototype.complete=function(){var h,g;(g=(h=this.destination)===null||h===void 0?void 0:h.complete)===null||g===void 0||g.call(h)},u.prototype._subscribe=function(h){var g,v;return(v=(g=this.source)===null||g===void 0?void 0:g.subscribe(h))!==null&&v!==void 0?v:EMPTY_SUBSCRIPTION},u}(Subject),dateTimestampProvider={now:function(){return(dateTimestampProvider.delegate||Date).now()},delegate:void 0},ReplaySubject=function(T){__extends(u,T);function u(h,g,v){h===void 0&&(h=1/0),g===void 0&&(g=1/0),v===void 0&&(v=dateTimestampProvider);var w=T.call(this)||this;return w._bufferSize=h,w._windowTime=g,w._timestampProvider=v,w._buffer=[],w._infiniteTimeWindow=!0,w._infiniteTimeWindow=g===1/0,w._bufferSize=Math.max(1,h),w._windowTime=Math.max(1,g),w}return u.prototype.next=function(h){var g=this,v=g.isStopped,w=g._buffer,C=g._infiniteTimeWindow,k=g._timestampProvider,U=g._windowTime;v||(w.push(h),!C&&w.push(k.now()+U)),this._trimBuffer(),T.prototype.next.call(this,h)},u.prototype._subscribe=function(h){this._throwIfClosed(),this._trimBuffer();for(var g=this._innerSubscribe(h),v=this,w=v._infiniteTimeWindow,C=v._buffer,k=C.slice(),U=0;U<k.length&&!h.closed;U+=w?1:2)h.next(k[U]);return this._checkFinalizedStatuses(h),g},u.prototype._trimBuffer=function(){var h=this,g=h._bufferSize,v=h._timestampProvider,w=h._buffer,C=h._infiniteTimeWindow,k=(C?1:2)*g;if(g<1/0&&k<w.length&&w.splice(0,w.length-k),!C){for(var U=v.now(),N=0,O=1;O<w.length&&w[O]<=U;O+=2)N=O;N&&w.splice(0,N+1)}},u}(Subject),DEFAULT_WEBSOCKET_CONFIG={url:"",deserializer:function(T){return JSON.parse(T.data)},serializer:function(T){return JSON.stringify(T)}},WEBSOCKETSUBJECT_INVALID_ERROR_OBJECT="WebSocketSubject.error must be called with an object with an error code, and an optional reason: { code: number, reason: string }",WebSocketSubject=function(T){__extends(u,T);function u(h,g){var v=T.call(this)||this;if(v._socket=null,h instanceof Observable)v.destination=g,v.source=h;else{var w=v._config=__assign({},DEFAULT_WEBSOCKET_CONFIG);if(v._output=new Subject,typeof h=="string")w.url=h;else for(var C in h)h.hasOwnProperty(C)&&(w[C]=h[C]);if(!w.WebSocketCtor&&WebSocket)w.WebSocketCtor=WebSocket;else if(!w.WebSocketCtor)throw new Error("no WebSocket constructor can be found");v.destination=new ReplaySubject}return v}return u.prototype.lift=function(h){var g=new u(this._config,this.destination);return g.operator=h,g.source=this,g},u.prototype._resetState=function(){this._socket=null,this.source||(this.destination=new ReplaySubject),this._output=new Subject},u.prototype.multiplex=function(h,g,v){var w=this;return new Observable(function(C){try{w.next(h())}catch(U){C.error(U)}var k=w.subscribe({next:function(U){try{v(U)&&C.next(U)}catch(N){C.error(N)}},error:function(U){return C.error(U)},complete:function(){return C.complete()}});return function(){try{w.next(g())}catch(U){C.error(U)}k.unsubscribe()}})},u.prototype._connectSocket=function(){var h=this,g=this._config,v=g.WebSocketCtor,w=g.protocol,C=g.url,k=g.binaryType,U=this._output,N=null;try{N=w?new v(C,w):new v(C),this._socket=N,k&&(this._socket.binaryType=k)}catch(d){U.error(d);return}var O=new Subscription(function(){h._socket=null,N&&N.readyState===1&&N.close()});N.onopen=function(d){var M=h._socket;if(!M){N.close(),h._resetState();return}var e=h._config.openObserver;e&&e.next(d);var b=h.destination;h.destination=Subscriber.create(function(z){if(N.readyState===1)try{var W=h._config.serializer;N.send(W(z))}catch(s0){h.destination.error(s0)}},function(z){var W=h._config.closingObserver;W&&W.next(void 0),z&&z.code?N.close(z.code,z.reason):U.error(new TypeError(WEBSOCKETSUBJECT_INVALID_ERROR_OBJECT)),h._resetState()},function(){var z=h._config.closingObserver;z&&z.next(void 0),N.close(),h._resetState()}),b&&b instanceof ReplaySubject&&O.add(b.subscribe(h.destination))},N.onerror=function(d){h._resetState(),U.error(d)},N.onclose=function(d){N===h._socket&&h._resetState();var M=h._config.closeObserver;M&&M.next(d),d.wasClean?U.complete():U.error(d)},N.onmessage=function(d){try{var M=h._config.deserializer;U.next(M(d))}catch(e){U.error(e)}}},u.prototype._subscribe=function(h){var g=this,v=this.source;return v?v.subscribe(h):(this._socket||this._connectSocket(),this._output.subscribe(h),h.add(function(){var w=g._socket;g._output.observers.length===0&&(w&&(w.readyState===1||w.readyState===0)&&w.close(),g._resetState())}),h)},u.prototype.unsubscribe=function(){var h=this._socket;h&&(h.readyState===1||h.readyState===0)&&h.close(),this._resetState(),T.prototype.unsubscribe.call(this)},u}(AnonymousSubject);function webSocket(T){return new WebSocketSubject(T)}var NVMESSAGE=(T=>(T[T.ZOOM=1]="ZOOM",T[T.CLIP_PLANE=2]="CLIP_PLANE",T[T.AZIMUTH_ELEVATION=3]="AZIMUTH_ELEVATION",T[T.FRAME_CHANGED=4]="FRAME_CHANGED",T[T.VOLUME_ADDED_FROM_URL=5]="VOLUME_ADDED_FROM_URL",T[T.VOLUME_WITH_URL_REMOVED=6]="VOLUME_WITH_URL_REMOVED",T[T.COLORMAP_CHANGED=7]="COLORMAP_CHANGED",T[T.OPACITY_CHANGED=8]="OPACITY_CHANGED",T[T.MESH_FROM_URL_ADDED=9]="MESH_FROM_URL_ADDED",T[T.MESH_WITH_URL_REMOVED=10]="MESH_WITH_URL_REMOVED",T[T.CUSTOM_SHADER_ADDED=11]="CUSTOM_SHADER_ADDED",T[T.SHADER_CHANGED=12]="SHADER_CHANGED",T[T.MESH_PROPERTY_CHANGED=13]="MESH_PROPERTY_CHANGED",T.USER_JOINED="user joined",T.CREATE="create",T.VOLUME_LOADED_FROM_URL="volume with url added",T))(NVMESSAGE||{});class SessionUser{constructor(u,h,g,v){g0(this,"id");g0(this,"displayName");g0(this,"key");g0(this,"properties");this.id=h||v4(),this.displayName=u||`user-${this.id}`,this.key=g||v4(),this.properties=v||new Map}}function storageAvailable(T){const u=window[T],h="test";try{return u.setItem(h,h),u.removeItem(h),!0}catch{return!1}}class SessionBus{constructor(u,h,g,v="",w=""){g0(this,"userList");g0(this,"user");g0(this,"userQueueName");g0(this,"userListName");g0(this,"onMessageCallback");g0(this,"isConnectedToServer",!1);g0(this,"isController",!1);g0(this,"sessionScene",{});g0(this,"sessionKey");g0(this,"sessionName");g0(this,"sessionSceneName");g0(this,"serverConnection$",null);if(this.userList=[],this.user=h||new SessionUser("anonymous"),this.onMessageCallback=g,this.sessionScene={},this.sessionKey=w||v4(),this.sessionName=u,this.sessionSceneName=`session-${u}-scene`,v)this.connectToServer(v,u),this.subscribeToServer(),this.isConnectedToServer=!0,this.serverConnection$!==null&&this.serverConnection$.next({op:NVMESSAGE.CREATE,key:this.sessionKey});else{if(!storageAvailable("localStorage"))throw new Error("Local storage unavailable");this.userQueueName=`user-${this.user.id}-q`,this.userListName=`${u}-user-list`,this.userList=JSON.parse(localStorage.getItem(this.userListName)||"[]"),this.userList.push(this.user),localStorage.setItem(this.userListName,JSON.stringify(this.userList)),localStorage.setItem(this.userQueueName,JSON.stringify([])),window.addEventListener("storage",this.localStorageEventListener.bind(this))}}sendSessionMessage(u){u.from=this.user.id,this.isConnectedToServer&&this.serverConnection$!==null?this.serverConnection$.next({...u,key:this.sessionKey,userKey:this.user.key}):this.sendLocalMessage(u)}connectToServer(u,h){const g=new URL(u);g.pathname="websockets",g.search="?session="+h,this.serverConnection$=webSocket(g.href),log.debug(g.href)}subscribeToServer(){this.serverConnection$!==null&&this.serverConnection$.subscribe({next:u=>{this.onMessageCallback(u)},error:u=>log.error(u),complete:()=>log.debug("complete")})}sendLocalMessage(u){for(const h of this.userList){if(h.id===this.user.id)continue;const g=`user-${h.id}-q`,v=localStorage.getItem(g),w=v?JSON.parse(v):[];w.push(u),localStorage.setItem(g,JSON.stringify(w))}}localStorageEventListener(u){if(u.newValue)switch(u.key){case this.userListName:{const h=JSON.parse(u.newValue),g=JSON.parse(u.oldValue??"[]");this.userList=h;const v=h.filter(w=>!g.map(C=>C.id).includes(w.id));for(const w of v)this.onMessageCallback({op:NVMESSAGE.USER_JOINED,user:w})}break;case this.userQueueName:{const h=JSON.parse(u.newValue);for(const g of h)this.onMessageCallback&&this.onMessageCallback(g);localStorage.setItem(this.userQueueName??"",JSON.stringify([]))}break}}}class NVController{constructor(u){g0(this,"niivue");g0(this,"mediaUrlMap");g0(this,"isInSession",!1);g0(this,"user");g0(this,"sessionBus");g0(this,"onFrameChange",(u,h)=>{});this.niivue=u,this.mediaUrlMap=new Map,this.niivue.onLocationChange=this.onLocationChangeHandler.bind(this),this.niivue.onZoom3DChange=this.onZoom3DChangeHandler.bind(this),this.niivue.scene.onAzimuthElevationChange=this.onAzimuthElevationChangeHandler.bind(this),this.niivue.onClipPlaneChange=this.onClipPlaneChangeHandler.bind(this),this.niivue.onVolumeAddedFromUrl=this.onVolumeAddedFromUrlHandler.bind(this),this.niivue.onVolumeWithUrlRemoved=this.onVolumeWithUrlRemovedHandler.bind(this),this.niivue.onMeshAddedFromUrl=this.onMeshAddedFromUrlHandler.bind(this),this.niivue.onMeshWithUrlRemoved=this.onMeshWithUrlRemovedHandler.bind(this),this.niivue.onCustomMeshShaderAdded=this.onCustomMeshShaderAddedHandler.bind(this),this.niivue.onMeshShaderChanged=this.onMeshShaderChanged.bind(this),this.niivue.onMeshPropertyChanged=this.onMeshPropertyChanged.bind(this),this.niivue.onFrameChange=this.onFrameChangeHandler.bind(this);for(const h of this.niivue.volumes)h.onColormapChange=this.onColormapChangeHandler.bind(this),h.onOpacityChange=this.onOpacityChangeHandler.bind(this)}onLocationChangeHandler(u){log.debug(u)}addVolume(u,h){this.niivue.volumes.push(u);const g=this.niivue.volumes.length===1?0:this.niivue.volumes.length-1;this.niivue.setVolume(u,g),this.niivue.mediaUrlMap.set(u,h)}addMesh(u,h){this.niivue.meshes.push(u);const g=this.niivue.meshes.length===1?0:this.niivue.meshes.length-1;this.niivue.setMesh(u,g),this.niivue.mediaUrlMap.set(u,h)}onNewMessage(u){switch(u.op){case NVMESSAGE.ZOOM:this.niivue.volScaleMultiplier=u.zoom;break;case NVMESSAGE.CLIP_PLANE:this.niivue.scene.clipPlane=u.clipPlane;break;case NVMESSAGE.AZIMUTH_ELEVATION:this.niivue.scene._elevation=u.elevation,this.niivue.scene._azimuth=u.azimuth;break;case NVMESSAGE.FRAME_CHANGED:{const h=this.niivue.getMediaByUrl(u.url);h&&(h.frame4D=u.index)}break;case NVMESSAGE.VOLUME_ADDED_FROM_URL:this.niivue.getMediaByUrl(u.imageOptions.url)||NVImage.loadFromUrl(u.imageOptions).then(h=>{h&&this.addVolume(h,u.imageOptions.url)}).catch(h=>{if(h)throw h});break;case NVMESSAGE.VOLUME_WITH_URL_REMOVED:{const h=this.niivue.getMediaByUrl(u.url);h&&(this.niivue.setVolume(h,-1),this.niivue.mediaUrlMap.delete(h))}break;case NVMESSAGE.COLORMAP_CHANGED:{const h=this.niivue.getMediaByUrl(u.url);h._colormap=u.colormap,this.niivue.updateGLVolume()}break;case NVMESSAGE.OPACITY_CHANGED:{const h=this.niivue.getMediaByUrl(u.url);h._opacity=u.opacity,this.niivue.updateGLVolume()}break;case NVMESSAGE.MESH_FROM_URL_ADDED:this.niivue.getMediaByUrl(u.meshOptions.url)||(u.meshOptions.gl=this.niivue.gl,NVMesh.loadFromUrl(u.meshOptions).then(h=>{this.addMesh(h,u.meshOptions.url)}).catch(h=>{if(h)throw h}));break;case NVMESSAGE.MESH_WITH_URL_REMOVED:{const h=this.niivue.getMediaByUrl(u.url);h&&(this.niivue.setMesh(h,-1),this.niivue.mediaUrlMap.delete(h))}break;case NVMESSAGE.CUSTOM_SHADER_ADDED:{const h=this.niivue.createCustomMeshShader(u.fragmentShaderText,u.name);this.niivue.meshShaders.push(h)}break;case NVMESSAGE.SHADER_CHANGED:this.niivue.meshes[u.meshIndex].meshShaderIndex=u.shaderIndex,this.niivue.updateGLVolume();break;case NVMESSAGE.MESH_PROPERTY_CHANGED:this.niivue.meshes[u.meshIndex].setProperty(u.key,u.val,this.niivue.gl);break}this.niivue.drawScene()}connectToSession(u,h,g,v){this.user=h||new SessionUser,this.sessionBus=new SessionBus(u,this.user,this.onNewMessage.bind(this),g,v),this.isInSession=!0}onZoom3DChangeHandler(u){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.ZOOM,zoom:u})}onAzimuthElevationChangeHandler(u,h){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.AZIMUTH_ELEVATION,azimuth:u,elevation:h})}onClipPlaneChangeHandler(u){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.CLIP_PLANE,clipPlane:u})}onVolumeAddedFromUrlHandler(u,h){this.isInSession&&this.sessionBus&&(log.debug(u),this.sessionBus.sendSessionMessage({op:NVMESSAGE.VOLUME_ADDED_FROM_URL,imageOptions:u})),h.onColormapChange=this.onColormapChangeHandler.bind(this),h.onOpacityChange=this.onOpacityChangeHandler.bind(this)}onImageLoadedHandler(u){if(u.onColormapChange=this.onColormapChangeHandler.bind(this),u.onOpacityChange=this.onOpacityChangeHandler.bind(this),this.isInSession&&this.sessionBus&&this.niivue.mediaUrlMap.has(u)){const h=this.niivue.mediaUrlMap.get(u);this.sessionBus.sendSessionMessage({op:NVMESSAGE.VOLUME_LOADED_FROM_URL,url:h})}}onVolumeWithUrlRemovedHandler(u){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.VOLUME_WITH_URL_REMOVED,url:u})}onMeshAddedFromUrlHandler(u){log.debug("mesh loaded from url"),log.debug(u),this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.MESH_FROM_URL_ADDED,meshOptions:u})}onMeshLoadedHandler(u){log.debug("mesh has been added"),log.debug(u)}onMeshWithUrlRemovedHandler(u){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.MESH_WITH_URL_REMOVED,url:u})}onColormapChangeHandler(u){if(this.isInSession&&this.sessionBus&&this.niivue.mediaUrlMap.has(u)){const h=this.niivue.mediaUrlMap.get(u),g=u.colormap;this.sessionBus.sendSessionMessage({op:NVMESSAGE.COLORMAP_CHANGED,url:h,colormap:g})}}onOpacityChangeHandler(u){if(this.isInSession&&this.sessionBus&&this.niivue.mediaUrlMap.has(u)){const h=this.niivue.mediaUrlMap.get(u),g=u.opacity;this.sessionBus.sendSessionMessage({op:NVMESSAGE.OPACITY_CHANGED,url:h,opacity:g})}}onFrameChangeHandler(u,h){if(log.debug("frame has changed to "+h),log.debug(u),this.niivue.mediaUrlMap.has(u)&&this.isInSession&&this.sessionBus){const g=this.niivue.mediaUrlMap.get(u);this.sessionBus.sendSessionMessage({op:NVMESSAGE.FRAME_CHANGED,url:g,index:h})}this.onFrameChange(u,h)}onCustomMeshShaderAddedHandler(u,h){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.CUSTOM_SHADER_ADDED,fragmentShaderText:u,name:h})}onMeshShaderChanged(u,h){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.SHADER_CHANGED,meshIndex:u,shaderIndex:h})}onMeshPropertyChanged(u,h,g){this.isInSession&&this.sessionBus&&(log.debug(NVMESSAGE.MESH_PROPERTY_CHANGED),this.sessionBus.sendSessionMessage({op:NVMESSAGE.MESH_PROPERTY_CHANGED,meshIndex:u,key:h,val:g}))}}const MESH_EXTENSIONS=["ASC","BYU","DFS","FSM","PIAL","ORIG","INFLATED","SMOOTHWM","SPHERE","WHITE","G","GEO","GII","ICO","MZ3","NV","OBJ","OFF","PLY","SRF","STL","TCK","TRACT","TRI","TRK","TT","TRX","VTK","X3D","JCON","JSON"],LEFT_MOUSE_BUTTON=0,CENTER_MOUSE_BUTTON=1,RIGHT_MOUSE_BUTTON=2,TEXTURE0_BACK_VOL=33984,TEXTURE1_COLORMAPS=33985,TEXTURE2_OVERLAY_VOL=33986,TEXTURE3_FONT=33987,TEXTURE4_THUMBNAIL=33988,TEXTURE5_MATCAP=33989,TEXTURE6_GRADIENT=33990,TEXTURE7_DRAW=33991,TEXTURE8_GRADIENT_TEMP=33992,TEXTURE9_ORIENT=33993,TEXTURE10_BLEND=33994,TEXTURE11_GC_BACK=33995,TEXTURE12_GC_STRENGTH0=33996,TEXTURE13_GC_STRENGTH1=33997,TEXTURE14_GC_LABEL0=33998,TEXTURE15_GC_LABEL1=33999,defaultSaveImageOptions={filename:"",isSaveDrawing:!1,volumeByIndex:0};class Niivue{constructor(u=DEFAULT_OPTIONS){g0(this,"canvas",null);g0(this,"_gl",null);g0(this,"isBusy",!1);g0(this,"needsRefresh",!1);g0(this,"colormapTexture",null);g0(this,"colormapLists",[]);g0(this,"volumeTexture",null);g0(this,"gradientTexture",null);g0(this,"gradientTextureAmount",0);g0(this,"drawTexture",null);g0(this,"drawUndoBitmaps",[]);g0(this,"drawLut",cmapper.makeDrawLut("$itksnap"));g0(this,"drawOpacity",.8);g0(this,"renderDrawAmbientOcclusion",.4);g0(this,"colorbarHeight",0);g0(this,"drawPenLocation",[NaN,NaN,NaN]);g0(this,"drawPenAxCorSag",-1);g0(this,"drawFillOverwrites",!0);g0(this,"drawPenFillPts",[]);g0(this,"overlayTexture",null);g0(this,"overlayTextureID",null);g0(this,"sliceMMShader");g0(this,"sliceV1Shader");g0(this,"orientCubeShader");g0(this,"orientCubeShaderVAO",null);g0(this,"rectShader");g0(this,"renderShader");g0(this,"lineShader");g0(this,"line3DShader");g0(this,"passThroughShader");g0(this,"renderGradientShader");g0(this,"renderSliceShader");g0(this,"renderVolumeShader");g0(this,"pickingMeshShader");g0(this,"pickingImageShader");g0(this,"colorbarShader");g0(this,"fontShader",null);g0(this,"fiberShader");g0(this,"fontTexture",null);g0(this,"circleShader");g0(this,"matCapTexture",null);g0(this,"bmpShader",null);g0(this,"bmpTexture",null);g0(this,"thumbnailVisible",!1);g0(this,"bmpTextureWH",1);g0(this,"growCutShader");g0(this,"orientShaderAtlasU",null);g0(this,"orientShaderAtlasI",null);g0(this,"orientShaderU",null);g0(this,"orientShaderI",null);g0(this,"orientShaderF",null);g0(this,"orientShaderRGBU",null);g0(this,"surfaceShader",null);g0(this,"blurShader",null);g0(this,"sobelShader",null);g0(this,"genericVAO",null);g0(this,"unusedVAO",null);g0(this,"crosshairs3D",null);g0(this,"DEFAULT_FONT_GLYPH_SHEET",defaultFontPNG);g0(this,"DEFAULT_FONT_METRICS",defaultFontMetrics);g0(this,"fontMetrics");g0(this,"fontMets",null);g0(this,"backgroundMasksOverlays",0);g0(this,"overlayOutlineWidth",0);g0(this,"overlayAlphaShader",1);g0(this,"isAlphaClipDark",!1);g0(this,"position");g0(this,"extentsMin");g0(this,"extentsMax");g0(this,"resizeObserver",null);g0(this,"syncOpts",{});g0(this,"readyForSync",!1);g0(this,"uiData",{mousedown:!1,touchdown:!1,mouseButtonLeftDown:!1,mouseButtonCenterDown:!1,mouseButtonRightDown:!1,mouseDepthPicker:!1,clickedTile:-1,pan2DxyzmmAtMouseDown:[0,0,0,1],prevX:0,prevY:0,currX:0,currY:0,currentTouchTime:0,lastTouchTime:0,touchTimer:null,doubleTouch:!1,isDragging:!1,dragStart:[0,0],dragEnd:[0,0],dragClipPlaneStartDepthAziElev:[0,0,0],lastTwoTouchDistance:0,multiTouchGesture:!1});g0(this,"back",null);g0(this,"overlays",[]);g0(this,"deferredVolumes",[]);g0(this,"deferredMeshes",[]);g0(this,"furthestVertexFromOrigin",100);g0(this,"volScale",[]);g0(this,"vox",[]);g0(this,"mousePos",[0,0]);g0(this,"screenSlices",[]);g0(this,"cuboidVertexBuffer");g0(this,"otherNV",null);g0(this,"volumeObject3D",null);g0(this,"pivot3D",[0,0,0]);g0(this,"furthestFromPivot",10);g0(this,"currentClipPlaneIndex",0);g0(this,"lastCalled",new Date().getTime());g0(this,"selectedObjectId",-1);g0(this,"CLIP_PLANE_ID",1);g0(this,"VOLUME_ID",254);g0(this,"DISTANCE_FROM_CAMERA",-.54);g0(this,"graph",{LTWH:[0,0,640,480],opacity:0,vols:[0],autoSizeMultiplanar:!1,normalizeValues:!1});g0(this,"meshShaders",[{Name:"Phong",Frag:fragMeshShader},{Name:"Matte",Frag:fragMeshMatteShader},{Name:"Harmonic",Frag:fragMeshShaderSHBlue},{Name:"Hemispheric",Frag:fragMeshHemiShader},{Name:"Edge",Frag:fragMeshEdgeShader},{Name:"Diffuse",Frag:fragMeshDiffuseEdgeShader},{Name:"Outline",Frag:fragMeshOutlineShader},{Name:"Toon",Frag:fragMeshToonShader},{Name:"Flat",Frag:fragFlatMeshShader},{Name:"Matcap",Frag:fragMeshMatcapShader}]);g0(this,"dragModes",{contrast:DRAG_MODE.contrast,measurement:DRAG_MODE.measurement,none:DRAG_MODE.none,pan:DRAG_MODE.pan,slicer3D:DRAG_MODE.slicer3D,callbackOnly:DRAG_MODE.callbackOnly});g0(this,"sliceTypeAxial",SLICE_TYPE.AXIAL);g0(this,"sliceTypeCoronal",SLICE_TYPE.CORONAL);g0(this,"sliceTypeSagittal",SLICE_TYPE.SAGITTAL);g0(this,"sliceTypeMultiplanar",SLICE_TYPE.MULTIPLANAR);g0(this,"sliceTypeRender",SLICE_TYPE.RENDER);g0(this,"onDragRelease",()=>{});g0(this,"onMouseUp",()=>{});g0(this,"onLocationChange",()=>{});g0(this,"onIntensityChange",()=>{});g0(this,"onImageLoaded",()=>{});g0(this,"onMeshLoaded",()=>{});g0(this,"onFrameChange",()=>{});g0(this,"onError",()=>{});g0(this,"onColormapChange",()=>{});g0(this,"onInfo",()=>{});g0(this,"onWarn",()=>{});g0(this,"onDebug",()=>{});g0(this,"onVolumeAddedFromUrl",()=>{});g0(this,"onVolumeWithUrlRemoved",()=>{});g0(this,"onVolumeUpdated",()=>{});g0(this,"onMeshAddedFromUrl",()=>{});g0(this,"onMeshAdded",()=>{});g0(this,"onMeshWithUrlRemoved",()=>{});g0(this,"onZoom3DChange",()=>{});g0(this,"onAzimuthElevationChange",()=>{});g0(this,"onClipPlaneChange",()=>{});g0(this,"onCustomMeshShaderAdded",()=>{});g0(this,"onMeshShaderChanged",()=>{});g0(this,"onMeshPropertyChanged",()=>{});g0(this,"onDocumentLoaded",()=>{});g0(this,"document",new NVDocument);g0(this,"mediaUrlMap",new Map);g0(this,"initialized",!1);g0(this,"currentDrawUndoBitmap");g0(this,"loadingText");for(const h in u)typeof u[h]=="function"?this[h]=u[h]:this.opts[h]=DEFAULT_OPTIONS[h]===void 0?DEFAULT_OPTIONS[h]:u[h];this.opts.isHighResolutionCapable?this.uiData.dpr=window.devicePixelRatio||1:this.uiData.dpr=1,this.currentDrawUndoBitmap=this.opts.maxDrawUndoBitmaps,this.opts.drawingEnabled&&this.createEmptyDrawing(),this.opts.thumbnail.length>0&&(this.thumbnailVisible=!0),this.loadingText=this.opts.loadingText,log.setLogLevel(this.opts.logLevel)}get scene(){return this.document.scene}get opts(){return this.document.opts}get sliceMosaicString(){return this.document.opts.sliceMosaicString||""}set sliceMosaicString(u){this.document.opts.sliceMosaicString=u}get volumes(){return this.document.volumes}set volumes(u){this.document.volumes=u}get meshes(){return this.document.meshes}set meshes(u){this.document.meshes=u}get drawBitmap(){return this.document.drawBitmap}set drawBitmap(u){this.document.drawBitmap=u}get volScaleMultiplier(){return this.scene.volScaleMultiplier}set volScaleMultiplier(u){this.setScale(u)}async saveScene(u="niivue.png"){function h(v,w){const C=document.createElement("a");document.body.appendChild(C),C.style.display="none";const k=window.URL.createObjectURL(v);C.href=k,C.download=w,C.click(),C.remove()}const g=this.canvas;if(!g)throw new Error("canvas not defined");this.drawScene(),g.toBlob(v=>{v&&(u===""&&(u=`niivue-screenshot-${new Date().toString()}.png`,u=u.replace(/\s/g,"_")),h(v,u))})}async attachTo(u,h=null){return await this.attachToCanvas(document.getElementById(u),h),log.debug("attached to element with id: ",u),this}async attachToCanvas(u,h=null){return this.canvas=u,h===null&&(h=navigator.hardwareConcurrency>6,log.debug("AntiAlias ",h," Threads ",navigator.hardwareConcurrency)),this.gl=this.canvas.getContext("webgl2",{alpha:!0,antialias:h}),log.info("NIIVUE VERSION ",version),this.canvas.parentElement.style.backgroundColor="black",this.opts.isResizeCanvas&&(this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.display="block",this.canvas.width=this.canvas.offsetWidth,this.canvas.height=this.canvas.offsetHeight,window.addEventListener("resize",this.resizeListener.bind(this)),this.resizeObserver=new ResizeObserver(this.resizeListener.bind(this)),this.resizeObserver.observe(this.canvas.parentElement)),this.registerInteractions(),await this.init(),this.drawScene(),this}syncWith(u,h={"2d":!0,"3d":!0}){this.otherNV=u,this.syncOpts=h}broadcastTo(u,h={"2d":!0,"3d":!0}){this.otherNV=u,this.syncOpts=h}sync(){if(!this.gl||!this.otherNV||typeof this.otherNV>"u"||!this.gl.canvas.matches(":focus"))return;const u=this.frac2mm(this.scene.crosshairPos);if(this.otherNV instanceof Niivue)this.syncOpts["2d"]&&(this.otherNV.scene.crosshairPos=this.otherNV.mm2frac(u)),this.syncOpts["3d"]&&(this.otherNV.scene.renderAzimuth=this.scene.renderAzimuth,this.otherNV.scene.renderElevation=this.scene.renderElevation),this.otherNV.drawScene(),this.otherNV.createOnLocationChange();else if(Array.isArray(this.otherNV))for(let h=0;h<this.otherNV.length;h++)this.otherNV[h]!==this&&(this.syncOpts["2d"]&&(this.otherNV[h].scene.crosshairPos=this.otherNV[h].mm2frac(u)),this.syncOpts["3d"]&&(this.otherNV[h].scene.renderAzimuth=this.scene.renderAzimuth,this.otherNV[h].scene.renderElevation=this.scene.renderElevation),this.otherNV[h].drawScene(),this.otherNV[h].createOnLocationChange())}arrayEquals(u,h){return Array.isArray(u)&&Array.isArray(h)&&u.length===h.length&&u.every((g,v)=>g===h[v])}resizeListener(){if(!(!this.canvas||!this.gl)){if(!this.opts.isResizeCanvas){this.opts.isHighResolutionCapable&&(log.warn("isHighResolutionCapable requires isResizeCanvas"),this.opts.isHighResolutionCapable=!1),this.uiData.dpr=1,this.drawScene();return}this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.display="block",this.opts.isHighResolutionCapable?(this.uiData.dpr=window.devicePixelRatio||1,log.debug("devicePixelRatio: "+this.uiData.dpr)):this.uiData.dpr=1,"width"in this.canvas.parentElement?(this.canvas.width=this.canvas.parentElement.width*this.uiData.dpr,this.canvas.height=this.canvas.parentElement.height*this.uiData.dpr):(this.canvas.width=this.canvas.offsetWidth*this.uiData.dpr,this.canvas.height=this.canvas.offsetHeight*this.uiData.dpr),this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height),this.drawScene()}}getRelativeMousePosition(u,h){if(h=h||u.target,!h)return;const g=h.getBoundingClientRect();return{x:u.clientX-g.left,y:u.clientY-g.top}}getNoPaddingNoBorderCanvasRelativeMousePosition(u,h){return h=h||u.target,this.getRelativeMousePosition(u,h)}mouseContextMenuListener(u){u.preventDefault()}mouseDownListener(u){u.preventDefault(),this.drawPenLocation=[NaN,NaN,NaN],this.drawPenAxCorSag=-1,this.uiData.mousedown=!0,log.debug("mouse down"),log.debug(u);const h=this.getNoPaddingNoBorderCanvasRelativeMousePosition(u,this.gl.canvas);if(!h)return;const[g,v]=[h.x*this.uiData.dpr,h.y*this.uiData.dpr],w=this.getLabelAtPoint([g,v]);if(w){for(const C of this.meshes)if(C.type===MeshType.CONNECTOME)for(const k of C.nodes)k.label===w&&(this.scene.crosshairPos=this.mm2frac([k.x,k.y,k.z]),this.updateGLVolume(),this.drawScene())}this.uiData.clickedTile=this.tileIndex(g,v),u.button===LEFT_MOUSE_BUTTON&&u.shiftKey?(this.uiData.mouseButtonCenterDown=!0,this.mouseCenterButtonHandler(u)):u.button===LEFT_MOUSE_BUTTON?(this.uiData.mouseButtonLeftDown=!0,this.mouseLeftButtonHandler(u)):u.button===RIGHT_MOUSE_BUTTON?(this.uiData.mouseButtonRightDown=!0,this.mouseRightButtonHandler(u)):u.button===CENTER_MOUSE_BUTTON&&(this.uiData.mouseButtonCenterDown=!0,this.mouseCenterButtonHandler(u))}mouseLeftButtonHandler(u){const h=this.getNoPaddingNoBorderCanvasRelativeMousePosition(u,this.gl.canvas);this.mouseDown(h.x,h.y),this.mouseClick(h.x,h.y)}mouseCenterButtonHandler(u){const h=this.getNoPaddingNoBorderCanvasRelativeMousePosition(u,this.gl.canvas);this.mousePos=[h.x*this.uiData.dpr,h.y*this.uiData.dpr],this.opts.dragMode!==DRAG_MODE.none&&(this.setDragStart(h.x,h.y),this.uiData.isDragging||(this.uiData.pan2DxyzmmAtMouseDown=clone(this.scene.pan2Dxyzmm)),this.uiData.isDragging=!0,this.uiData.dragClipPlaneStartDepthAziElev=this.scene.clipPlaneDepthAziElev)}mouseRightButtonHandler(u){const h=this.getNoPaddingNoBorderCanvasRelativeMousePosition(u,this.gl.canvas);this.mousePos=[h.x*this.uiData.dpr,h.y*this.uiData.dpr],this.opts.dragMode!==DRAG_MODE.none&&(this.setDragStart(h.x,h.y),this.uiData.isDragging||(this.uiData.pan2DxyzmmAtMouseDown=clone(this.scene.pan2Dxyzmm)),this.uiData.isDragging=!0,this.uiData.dragClipPlaneStartDepthAziElev=this.scene.clipPlaneDepthAziElev)}calculateMinMaxVoxIdx(u){if(u.length>2)throw new Error("array must not contain more than two values");return[Math.floor(Math.min(u[0],u[1])),Math.floor(Math.max(u[0],u[1]))]}calculateNewRange({volIdx:u=0}={}){if(this.opts.sliceType===SLICE_TYPE.RENDER&&this.sliceMosaicString.length<1||this.uiData.dragStart[0]===this.uiData.dragEnd[0]&&this.uiData.dragStart[1]===this.uiData.dragEnd[1])return;let h=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]);if(h[0]<0)return;const g=this.frac2vox(h,u);if(h=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]),h[0]<0)return;const v=this.frac2vox(h,u);let w=-Number.MAX_VALUE,C=Number.MAX_VALUE;const k=this.calculateMinMaxVoxIdx([g[0],v[0]]),U=this.calculateMinMaxVoxIdx([g[1],v[1]]),N=this.calculateMinMaxVoxIdx([g[2],v[2]]);g[0]-v[0]===0?k[1]=g[0]+1:g[1]-v[1]===0?U[1]=g[1]+1:g[2]-v[2]===0&&(N[1]=g[2]+1);const O=this.volumes[u].hdr,d=this.volumes[u].img;if(!O||!d)return;const M=O.dims[1],e=O.dims[2];for(let W=N[0];W<N[1];W++){const s0=W*M*e;for(let K=U[0];K<U[1];K++){const J=K*M;for(let D=k[0];D<k[1];D++){const Z=s0+J+D;C>d[Z]&&(C=d[Z]),w<d[Z]&&(w=d[Z])}}}if(C>=w)return;const b=intensityRaw2Scaled(O,C),z=intensityRaw2Scaled(O,w);this.volumes[u].cal_min=b,this.volumes[u].cal_max=z,this.onIntensityChange(this.volumes[u])}generateMouseUpCallback(u,h){const g=this.tileIndex(this.uiData.dragStart[0],this.uiData.dragStart[1]),v=this.tileIndex(this.uiData.dragEnd[0],this.uiData.dragEnd[1]);let w=-1;g===v&&(w=v);let C=-1;w>=0&&(C=this.screenSlices[w].axCorSag);const k=this.frac2mm(u),U=this.frac2mm(h),N=create$2();sub$1(N,fromValues$2(k[0],k[1],k[2]),fromValues$2(U[0],U[1],U[2]));const O=len(N),d=this.frac2vox(u),M=this.frac2vox(h);this.onDragRelease({fracStart:u,fracEnd:h,voxStart:d,voxEnd:M,mmStart:k,mmEnd:U,mmLength:O,tileIdx:w,axCorSag:C})}mouseUpListener(){function u(v){return Object.prototype.toString.call(v).indexOf("Function")>-1}const h={mouseButtonRightDown:this.uiData.mouseButtonRightDown,mouseButtonCenterDown:this.uiData.mouseButtonCenterDown,isDragging:this.uiData.isDragging,mousePos:this.mousePos,fracPos:this.canvasPos2frac(this.mousePos)};this.uiData.mousedown=!1,this.uiData.mouseButtonRightDown=!1;const g=this.uiData.mouseButtonCenterDown;if(this.uiData.mouseButtonCenterDown=!1,this.uiData.mouseButtonLeftDown=!1,this.drawPenFillPts.length>0?this.drawPenFilled():this.drawPenAxCorSag>=0&&this.drawAddUndoBitmap(),this.drawPenLocation=[NaN,NaN,NaN],this.drawPenAxCorSag=-1,u(this.onMouseUp)&&this.onMouseUp(h),this.uiData.isDragging){this.uiData.isDragging=!1,this.opts.dragMode===DRAG_MODE.callbackOnly&&this.drawScene();const v=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]),w=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);if(this.generateMouseUpCallback(v,w),this.opts.dragMode!==DRAG_MODE.contrast||g||this.uiData.dragStart[0]===this.uiData.dragEnd[0]&&this.uiData.dragStart[1]===this.uiData.dragEnd[1])return;this.calculateNewRange({volIdx:0}),this.refreshLayers(this.volumes[0],0)}this.drawScene()}checkMultitouch(u){if(this.uiData.touchdown&&!this.uiData.multiTouchGesture){const h=this.canvas.getBoundingClientRect();this.mouseDown(u.touches[0].clientX-h.left,u.touches[0].clientY-h.top),this.mouseClick(u.touches[0].clientX-h.left,u.touches[0].clientY-h.top)}}touchStartListener(u){u.preventDefault(),this.uiData.touchTimer||(this.uiData.touchTimer=setTimeout(()=>{this.resetBriCon(u)},this.opts.longTouchTimeout)),this.uiData.touchdown=!0,this.uiData.currentTouchTime=new Date().getTime();const h=this.uiData.currentTouchTime-this.uiData.lastTouchTime;if(h<this.opts.doubleTouchTimeout&&h>0){this.uiData.doubleTouch=!0,this.setDragStart(u.targetTouches[0].clientX-u.target.getBoundingClientRect().left,u.targetTouches[0].clientY-u.target.getBoundingClientRect().top),this.resetBriCon(u),this.uiData.lastTouchTime=this.uiData.currentTouchTime;return}else this.uiData.doubleTouch=!1,this.setDragStart(0,0),this.setDragEnd(0,0),this.uiData.lastTouchTime=this.uiData.currentTouchTime;this.uiData.touchdown&&u.touches.length<2?this.uiData.multiTouchGesture=!1:this.uiData.multiTouchGesture=!0,setTimeout(this.checkMultitouch.bind(this),1,u)}touchEndListener(u){if(u.preventDefault(),this.uiData.touchdown=!1,this.uiData.lastTwoTouchDistance=0,this.uiData.multiTouchGesture=!1,this.uiData.touchTimer&&(clearTimeout(this.uiData.touchTimer),this.uiData.touchTimer=null),this.uiData.isDragging){this.uiData.isDragging=!1,this.opts.dragMode===DRAG_MODE.contrast&&(this.calculateNewRange(),this.refreshLayers(this.volumes[0],0));const h=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]),g=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);this.generateMouseUpCallback(h,g)}this.mouseUpListener()}mouseMoveListener(u){if(this.uiData.mousedown){const h=this.getNoPaddingNoBorderCanvasRelativeMousePosition(u,this.gl.canvas);if(!h)return;const g=h.x*this.uiData.dpr,v=h.y*this.uiData.dpr;if(this.tileIndex(g,v)!==this.uiData.clickedTile)return;this.uiData.mouseButtonLeftDown?(this.mouseMove(h.x,h.y),this.mouseClick(h.x,h.y)):(this.uiData.mouseButtonRightDown||this.uiData.mouseButtonCenterDown)&&this.setDragEnd(h.x,h.y),this.drawScene(),this.uiData.prevX=this.uiData.currX,this.uiData.prevY=this.uiData.currY}}resetBriCon(u=null){if(this.uiData.isDragging)return;let h=!1;this.opts.sliceType===SLICE_TYPE.RENDER&&(h=!0);let g=0,v=0;if(u!==null&&("targetTouches"in u?(g=u.targetTouches[0].clientX-u.target.getBoundingClientRect().left,v=u.targetTouches[0].clientY-u.target.getBoundingClientRect().top):(g=u.offsetX,v=u.offsetY),g*=this.uiData.dpr,v*=this.uiData.dpr,this.inRenderTile(g,v)>=0&&(h=!0)),h){this.uiData.mouseDepthPicker=!0,this.drawScene(),this.drawScene();return}this.opts.dragMode!==DRAG_MODE.slicer3D&&(this.volumes.length<1||this.uiData.doubleTouch||(this.volumes[0].cal_min=this.volumes[0].robust_min,this.volumes[0].cal_max=this.volumes[0].robust_max,this.onIntensityChange(this.volumes[0]),this.refreshLayers(this.volumes[0],0),this.drawScene()))}setDragStart(u,h){u*=this.uiData.dpr,h*=this.uiData.dpr,this.uiData.dragStart[0]=u,this.uiData.dragStart[1]=h}setDragEnd(u,h){u*=this.uiData.dpr,h*=this.uiData.dpr,this.uiData.dragEnd[0]=u,this.uiData.dragEnd[1]=h}touchMoveListener(u){if(this.uiData.touchdown&&u.touches.length<2){const h=this.canvas.getBoundingClientRect();if(this.uiData.isDragging||(this.uiData.pan2DxyzmmAtMouseDown=clone(this.scene.pan2Dxyzmm)),this.uiData.isDragging=!0,this.uiData.doubleTouch&&this.uiData.isDragging){this.setDragEnd(u.targetTouches[0].clientX-u.target.getBoundingClientRect().left,u.targetTouches[0].clientY-u.target.getBoundingClientRect().top),this.drawScene();return}this.mouseClick(u.touches[0].clientX-h.left,u.touches[0].clientY-h.top),this.mouseMove(u.touches[0].clientX-h.left,u.touches[0].clientY-h.top)}else this.handlePinchZoom(u)}handlePinchZoom(u){if(u.targetTouches.length===2&&u.changedTouches.length===2){const h=Math.hypot(u.touches[0].pageX-u.touches[1].pageX,u.touches[0].pageY-u.touches[1].pageY),g=this.canvas.getBoundingClientRect();this.mousePos=[u.touches[0].clientX-g.left,u.touches[0].clientY-g.top],h<this.uiData.lastTwoTouchDistance?this.sliceScroll2D(-.01,u.touches[0].clientX-g.left,u.touches[0].clientY-g.top):this.sliceScroll2D(.01,u.touches[0].clientX-g.left,u.touches[0].clientY-g.top),this.uiData.lastTwoTouchDistance=h}}keyUpListener(u){if(u.code===this.opts.clipPlaneHotKey){const h=new Date().getTime();if(h-this.lastCalled>this.opts.keyDebounceTime){switch(this.currentClipPlaneIndex=(this.currentClipPlaneIndex+1)%7,this.currentClipPlaneIndex){case 0:this.scene.clipPlaneDepthAziElev=[2,0,0];break;case 1:this.scene.clipPlaneDepthAziElev=[0,270,0];break;case 2:this.scene.clipPlaneDepthAziElev=[0,90,0];break;case 3:this.scene.clipPlaneDepthAziElev=[0,0,0];break;case 4:this.scene.clipPlaneDepthAziElev=[0,180,0];break;case 5:this.scene.clipPlaneDepthAziElev=[0,0,-90];break;case 6:this.scene.clipPlaneDepthAziElev=[0,0,90];break}this.setClipPlane(this.scene.clipPlaneDepthAziElev)}this.lastCalled=h}else if(u.code===this.opts.viewModeHotKey){const h=new Date().getTime();h-this.lastCalled>this.opts.keyDebounceTime&&(this.setSliceType((this.opts.sliceType+1)%5),this.lastCalled=h)}}keyDownListener(u){u.code==="KeyH"&&this.opts.sliceType===SLICE_TYPE.RENDER?this.setRenderAzimuthElevation(this.scene.renderAzimuth-1,this.scene.renderElevation):u.code==="KeyL"&&this.opts.sliceType===SLICE_TYPE.RENDER?this.setRenderAzimuthElevation(this.scene.renderAzimuth+1,this.scene.renderElevation):u.code==="KeyJ"&&this.opts.sliceType===SLICE_TYPE.RENDER?this.setRenderAzimuthElevation(this.scene.renderAzimuth,this.scene.renderElevation+1):u.code==="KeyK"&&this.opts.sliceType===SLICE_TYPE.RENDER?this.setRenderAzimuthElevation(this.scene.renderAzimuth,this.scene.renderElevation-1):u.code==="KeyH"&&this.opts.sliceType!==SLICE_TYPE.RENDER?this.moveCrosshairInVox(-1,0,0):u.code==="KeyL"&&this.opts.sliceType!==SLICE_TYPE.RENDER?this.moveCrosshairInVox(1,0,0):u.code==="KeyU"&&this.opts.sliceType!==SLICE_TYPE.RENDER&&u.ctrlKey?this.moveCrosshairInVox(0,0,1):u.code==="KeyD"&&this.opts.sliceType!==SLICE_TYPE.RENDER&&u.ctrlKey?this.moveCrosshairInVox(0,0,-1):u.code==="KeyJ"&&this.opts.sliceType!==SLICE_TYPE.RENDER?this.moveCrosshairInVox(0,-1,0):u.code==="KeyK"&&this.opts.sliceType!==SLICE_TYPE.RENDER?this.moveCrosshairInVox(0,1,0):u.code==="KeyM"&&this.opts.sliceType!==SLICE_TYPE.RENDER?(this.opts.dragMode++,this.opts.dragMode>=DRAG_MODE.slicer3D&&(this.opts.dragMode=DRAG_MODE.none),log.info("drag mode changed to ",DRAG_MODE[this.opts.dragMode])):u.code==="ArrowLeft"?this.setFrame4D(this.volumes[0].id,this.volumes[0].frame4D-1):u.code==="ArrowRight"?this.setFrame4D(this.volumes[0].id,this.volumes[0].frame4D+1):u.code==="Slash"&&u.shiftKey&&alert(`NIIVUE VERSION: ${version}`)}wheelListener(u){if(u.preventDefault(),u.stopPropagation(),this.thumbnailVisible)return;const h=this.canvas.getBoundingClientRect();u.deltaY<0?this.sliceScroll2D(-.01,u.clientX-h.left,u.clientY-h.top):this.sliceScroll2D(.01,u.clientX-h.left,u.clientY-h.top)}registerInteractions(){if(!this.canvas)throw new Error("canvas undefined");this.canvas.addEventListener("mousedown",this.mouseDownListener.bind(this)),this.canvas.addEventListener("mouseup",this.mouseUpListener.bind(this)),this.canvas.addEventListener("mousemove",this.mouseMoveListener.bind(this)),this.canvas.addEventListener("touchstart",this.touchStartListener.bind(this)),this.canvas.addEventListener("touchend",this.touchEndListener.bind(this)),this.canvas.addEventListener("touchmove",this.touchMoveListener.bind(this)),this.canvas.addEventListener("wheel",this.wheelListener.bind(this)),this.canvas.addEventListener("contextmenu",this.mouseContextMenuListener.bind(this)),this.canvas.addEventListener("dblclick",this.resetBriCon.bind(this)),this.canvas.addEventListener("dragenter",this.dragEnterListener.bind(this),!1),this.canvas.addEventListener("dragover",this.dragOverListener.bind(this),!1),this.canvas.addEventListener("drop",this.dropListener.bind(this),!1),this.canvas.setAttribute("tabindex","0"),this.canvas.addEventListener("keyup",this.keyUpListener.bind(this),!1),this.canvas.addEventListener("keydown",this.keyDownListener.bind(this),!1)}dragEnterListener(u){u.stopPropagation(),u.preventDefault()}dragOverListener(u){u.stopPropagation(),u.preventDefault()}getFileExt(u,h=!0){log.debug("fullname: ",u);const g=/(?:\.([^.]+))?$/;let v=g.exec(u)[1];return v=v.toUpperCase(),v==="GZ"&&(v=g.exec(u.slice(0,-3))[1],v=v.toUpperCase()),h?v:v.toLowerCase()}async addVolumeFromUrl(u){const h=await NVImage.loadFromUrl(u);return this.document.addImageOptions(h,u),h.onColormapChange=this.onColormapChange,this.mediaUrlMap.set(h,u.url),this.onVolumeAddedFromUrl&&this.onVolumeAddedFromUrl(u,h),this.addVolume(h),h}getMediaByUrl(u){return[...this.mediaUrlMap.entries()].filter(h=>h[1]===u).map(h=>h[0]).pop()}removeVolumeByUrl(u){const h=this.getMediaByUrl(u);if(h)this.removeVolume(h);else throw new Error("No volume with URL present")}readDirectory(u){const h=u.createReader();let g=[];const v=async C=>{const k=[],U=async N=>new Promise((O,d)=>N.file(O,d));for(let N=0;N<C.length;N++)k.push(await U(C[N]));return k},w=()=>{h.readEntries(C=>{C.length?(g=g.concat(C),w()):v(g).then(k=>{NVImage.loadFromFile({file:k,name:u.name,urlImgData:null,imageType:NVIMAGE_TYPE.DCM_FOLDER}).then(U=>this.addVolume(U)).catch(U=>{throw U})}).catch(k=>{throw k})})};return w(),g}isMeshExt(u){const h=this.getFileExt(u);return log.debug("dropped ext"),log.debug(h),MESH_EXTENSIONS.includes(h)}async loadFromArrayBuffer(u,h){const g=this.getFileExt(h);if(MESH_EXTENSIONS.includes(g)){await this.addMeshFromUrl({url:h,buffer:u});return}const v=NVImageFromUrlOptions(h);v.buffer=u,v.name=h,await this.addVolumeFromUrl(v)}async loadFromFile(u){const h=this.getFileExt(u.name);if(MESH_EXTENSIONS.includes(h)){await NVMesh.loadFromFile({file:u,gl:this.gl,name:u.name}).then(g=>{this.addMesh(g)});return}await NVImage.loadFromFile({file:u,name:u.name}).then(g=>{this.addVolume(g)})}dropListener(u){if(u.stopPropagation(),u.preventDefault(),!this.opts.dragAndDropEnabled)return;const h=u.dataTransfer;if(!h)return;const g=h.getData("text/uri-list");if(g){const v=NVImageFromUrlOptions(g),w=this.getFileExt(g);log.debug("dropped ext"),log.debug(w),MESH_EXTENSIONS.includes(w)?this.addMeshFromUrl({url:g}).catch(C=>{throw C}):w==="NVD"?this.loadDocumentFromUrl(g).catch(C=>{throw C}):this.addVolumeFromUrl(v).catch(C=>{throw C})}else{const v=h.items;if(v.length>0){!u.shiftKey&&!u.altKey&&(this.volumes=[],this.overlays=[],this.meshes=[]),this.closeDrawing();for(const w of Array.from(v)){const C=w.webkitGetAsEntry();if(log.debug(C),!C)throw new Error("could not get entry from file");if(C.isFile){const k=this.getFileExt(C.name);if(k==="PNG"){C.file(N=>{this.loadBmpTexture(N).catch(O=>{throw O})});continue}let U;if(C.name.lastIndexOf("HEAD")!==-1)for(const N of Array.from(v)){const O=N.webkitGetAsEntry();if(!O)throw new Error("could not get paired entry");const d=C.name.substring(0,C.name.lastIndexOf("HEAD")),M=O.name.substring(0,O.name.lastIndexOf("BRIK"));d===M&&(U=O)}if(C.name.lastIndexOf("BRIK")!==-1)continue;if(MESH_EXTENSIONS.includes(k)){C.file(N=>{NVMesh.loadFromFile({file:N,gl:this.gl,name:N.name}).then(O=>{this.addMesh(O)}).catch(O=>{throw O})});continue}else if(k==="NVD"){C.file(N=>{NVDocument.loadFromFile(N).then(O=>{this.loadDocument(O),log.debug("loaded document")}).catch(O=>{throw O})});break}C.file(N=>{U?U.file(O=>{NVImage.loadFromFile({file:N,urlImgData:O,limitFrames4D:this.opts.limitFrames4D}).then(d=>{this.addVolume(d)}).catch(d=>{throw d})}):NVImage.loadFromFile({file:N,urlImgData:U,limitFrames4D:this.opts.limitFrames4D}).then(O=>{u.altKey?(log.debug("alt key detected: assuming this is a drawing overlay"),this.drawClearAllUndoBitmaps(),this.loadDrawing(O)):this.addVolume(O)}).catch(O=>{throw O})})}else C.isDirectory&&this.readDirectory(C)}}}this.drawScene()}setMultiplanarPadPixels(u){this.opts.multiplanarPadPixels=u,this.drawScene()}setMultiplanarLayout(u){typeof u=="string"&&(u=parseInt(u)),this.opts.multiplanarLayout=u,this.drawScene()}setCornerOrientationText(u){this.opts.isCornerOrientationText=u,this.updateGLVolume()}setRadiologicalConvention(u){this.opts.isRadiologicalConvention=u,this.updateGLVolume()}setDefaults(u={},h=!1){this.document.opts={...DEFAULT_OPTIONS},this.scene.sceneData={...INITIAL_SCENE_DATA};for(const g in u)typeof u[g]=="function"?this[g]=u[g]:this.opts[g]=DEFAULT_OPTIONS[g]===void 0?DEFAULT_OPTIONS[g]:u[g];if(this.scene.pan2Dxyzmm=[0,0,0,1],h&&this.volumes&&this.volumes.length>0)for(let g=0;g<this.volumes.length;g++)this.volumes[g].cal_min=this.volumes[g].robust_min,this.volumes[g].cal_max=this.volumes[g].robust_max;this.updateGLVolume()}setMeshThicknessOn2D(u){this.opts.meshThicknessOn2D=u,this.updateGLVolume()}setSliceMosaicString(u){this.sliceMosaicString=u,this.updateGLVolume()}setSliceMM(u){this.opts.isSliceMM=u,this.updateGLVolume()}setAdditiveBlend(u){this.opts.isAdditiveBlend=u,this.updateGLVolume()}getRadiologicalConvention(){return this.opts.isRadiologicalConvention}setHighResolutionCapable(u){this.opts.isHighResolutionCapable=u,u&&!this.opts.isResizeCanvas&&(log.warn("isHighResolutionCapable requires isResizeCanvas"),this.opts.isHighResolutionCapable=!1),this.opts.isHighResolutionCapable||(this.uiData.dpr=1),this.resizeListener(),this.drawScene()}addVolume(u){this.volumes.push(u);const h=this.volumes.length===1?0:this.volumes.length-1;this.setVolume(u,h),this.onImageLoaded(u),log.debug("loaded volume",u.name),log.debug(u)}addMesh(u){this.meshes.push(u);const h=this.meshes.length===1?0:this.meshes.length-1;this.setMesh(u,h),this.onMeshLoaded(u)}getVolumeIndexByID(u){const h=this.volumes.length;for(let g=0;g<h;g++)if(this.volumes[g].id===u)return g;return-1}drawAddUndoBitmap(){if(!this.drawBitmap||this.drawBitmap.length<1){log.debug("drawAddUndoBitmap error: No drawing open");return}this.currentDrawUndoBitmap++,this.currentDrawUndoBitmap>=this.opts.maxDrawUndoBitmaps&&(this.currentDrawUndoBitmap=0),this.drawUndoBitmaps[this.currentDrawUndoBitmap]=encodeRLE(this.drawBitmap)}drawClearAllUndoBitmaps(){if(this.currentDrawUndoBitmap=this.opts.maxDrawUndoBitmaps,!(!this.drawUndoBitmaps||this.drawUndoBitmaps.length<1))for(let u=this.drawUndoBitmaps.length-1;u>=0;u--)this.drawUndoBitmaps[u]=new Uint8Array}drawUndo(){if(this.drawUndoBitmaps.length<1){log.debug("undo bitmaps not loaded");return}if(this.currentDrawUndoBitmap--,this.currentDrawUndoBitmap<0&&(this.currentDrawUndoBitmap=this.drawUndoBitmaps.length-1),this.currentDrawUndoBitmap>=this.drawUndoBitmaps.length&&(this.currentDrawUndoBitmap=0),this.drawUndoBitmaps[this.currentDrawUndoBitmap].length<2){log.debug("drawUndo is misbehaving");return}this.drawBitmap=decodeRLE(this.drawUndoBitmaps[this.currentDrawUndoBitmap],this.drawBitmap.length),this.refreshDrawing(!0)}loadDrawing(u){if(this.drawBitmap&&log.debug("Overwriting open drawing!"),!this.back)throw new Error("back undefined");this.drawClearAllUndoBitmaps();const h=u.hdr.dims;if(h[1]!==this.back.hdr.dims[1]||h[2]!==this.back.hdr.dims[2]||h[3]!==this.back.hdr.dims[3])return log.debug("drawing dimensions do not match background image"),!1;u.img.constructor!==Uint8Array&&log.debug("Drawings should be UINT8");const g=u.permRAS,v=h[1]*h[2]*h[3];this.drawBitmap=new Uint8Array(v),this.drawTexture=this.r8Tex(this.drawTexture,TEXTURE7_DRAW,this.back.dims,!0);const w=[0,0,0];for(let z=0;z<3;z++)for(let W=0;W<3;W++)Math.abs(g[z])-1===W&&(w[W]=z*Math.sign(g[z]));let C=1;const k=[1,1,1],U=[!1,!1,!1];for(let z=0;z<w.length;z++)for(let W=0;W<w.length;W++)Math.abs(w[W])===z&&(k[W]=C,(w[W]<0||Object.is(w[W],-0))&&(U[W]=!0),C*=h[W+1]);let N=NVUtilities.range(0,h[1]-1,1);U[0]&&(N=NVUtilities.range(h[1]-1,0,-1));for(let z=0;z<h[1];z++)N[z]*=k[0];let O=NVUtilities.range(0,h[2]-1,1);U[1]&&(O=NVUtilities.range(h[2]-1,0,-1));for(let z=0;z<h[2];z++)O[z]*=k[1];let d=NVUtilities.range(0,h[3]-1,1);U[2]&&(d=NVUtilities.range(h[3]-1,0,-1));for(let z=0;z<h[3];z++)d[z]*=k[2];const M=u.img,e=this.drawBitmap;let b=0;for(let z=0;z<h[3];z++)for(let W=0;W<h[2];W++)for(let s0=0;s0<h[1];s0++)e[N[s0]+O[W]+d[z]]=M[b],b++;return this.drawAddUndoBitmap(),this.refreshDrawing(!1),this.drawScene(),!0}binarize(u){const h=u.hdr.dims,g=h[1]*h[2]*h[3],v=new Uint8Array(g);for(let w=0;w<g;w++)u.img[w]!==0&&(v[w]=1);u.img=v,u.hdr.datatypeCode=NiiDataType.DT_UINT8,u.hdr.cal_min=0,u.hdr.cal_max=1}async loadDrawingFromUrl(u,h=!1){this.drawBitmap&&log.debug("Overwriting open drawing!"),this.drawClearAllUndoBitmaps();let g=!1;try{const v=await NVImage.loadFromUrl(NVImageFromUrlOptions(u));h&&await this.binarize(v),g=this.loadDrawing(v)}catch{log.error("loadDrawingFromUrl() failed to load "+u),this.drawClearAllUndoBitmaps()}return g}findOtsu(u=2){if(this.volumes.length<1)return[];const h=this.volumes[0].img,g=h.length;if(g<1)return[];const v=256,w=v-1,C=new Array(v).fill(0),k=this.volumes[0].cal_min,U=this.volumes[0].cal_max;if(U<=k)return[];const N=(U-k)/v;function O(K){return K*N+k}const d=(v-1)/Math.abs(U-k),M=this.volumes[0].hdr.scl_inter,e=this.volumes[0].hdr.scl_slope;for(let K=0;K<g;K++){let J=h[K]*e+M;J=Math.min(Math.max(J,k),U),J=Math.round((J-k)*d),C[J]++}const b=Array(v).fill(0).map(()=>Array(v).fill(0)),z=Array(v).fill(0).map(()=>Array(v).fill(0));for(let K=1;K<v;++K)b[K][K]=C[K],z[K][K]=K*C[K];for(let K=1;K<v-1;++K)b[1][K+1]=b[1][K]+C[K+1],z[1][K+1]=z[1][K]+(K+1)*C[K+1];for(let K=2;K<v;K++)for(let J=K+1;J<v;J++)b[K][J]=b[1][J]-b[1][K-1],z[K][J]=z[1][J]-z[1][K-1];for(let K=1;K<v;++K)for(let J=K+1;J<v;J++)b[K][J]!==0&&(b[K][J]=z[K][J]*z[K][J]/b[K][J]);let W=0;const s0=[1/0,1/0,1/0];if(u>3)for(let K=0;K<v-3;K++)for(let J=K+1;J<v-2;J++)for(let D=J+1;D<v-1;D++){const Z=b[0][K]+b[K+1][J]+b[J+1][D]+b[D+1][w];Z>W&&(s0[0]=K,s0[1]=J,s0[2]=D,W=Z)}else if(u===3)for(let K=0;K<v-2;K++)for(let J=K+1;J<v-1;J++){const D=b[0][K]+b[K+1][J]+b[J+1][w];D>W&&(s0[0]=K,s0[1]=J,W=D)}else for(let K=0;K<v-1;K++){const J=b[0][K]+b[K+1][w];J>W&&(s0[0]=K,W=J)}return[O(s0[0]),O(s0[1]),O(s0[2])]}drawOtsu(u=2){if(this.volumes.length===0)return;const h=this.volumes[0].img.length,g=this.findOtsu(u);if(g.length<3)return;this.drawBitmap||this.createEmptyDrawing();const v=this.drawBitmap,w=this.volumes[0].img;for(let C=0;C<h;C++){if(v[C]!==0)continue;const k=w[C];k>g[0]&&(v[C]=1),k>g[1]&&(v[C]=2),k>g[2]&&(v[C]=3)}this.drawAddUndoBitmap(),this.refreshDrawing(!0)}removeHaze(u=5,h=0){const g=this.volumes[h].img,v=this.volumes[h].hdr,w=g.length;let C=2;(u===5||u===1)&&(C=4),(u===4||u===2)&&(C=3);const k=this.findOtsu(C);if(k.length<3)return;let U=k[0];u===1&&(U=k[2]),u===2&&(U=k[1]);const N=v.scl_inter,O=v.scl_slope,d=this.volumes[h].global_min;for(let M=0;M<w;M++)g[M]*O+N<U&&(g[M]=d);this.refreshLayers(this.volumes[h],0),this.drawScene()}saveImage(u=defaultSaveImageOptions){var k;const h={...defaultSaveImageOptions,...u},{filename:g,isSaveDrawing:v,volumeByIndex:w}=h;if(log.debug("saveImage",g,v,w),((k=this.back)==null?void 0:k.dims)===void 0)return log.debug("No voxelwise image open"),!1;if(v){if(!this.drawBitmap)return log.debug("No drawing open"),!1;const U=this.volumes[0].permRAS;if(U[0]===1&&U[1]===2&&U[2]===3)return log.debug("saving drawing"),this.volumes[0].saveToDisk(g,this.drawBitmap);{log.debug("saving drawing");const N=this.volumes[0].hdr.dims,O=[0,0,0];for(let Z=0;Z<3;Z++)for(let X=0;X<3;X++)Math.abs(U[Z])-1===X&&(O[X]=Z*Math.sign(U[Z]));let d=1;const M=[1,1,1],e=[!1,!1,!1];for(let Z=0;Z<O.length;Z++)for(let X=0;X<O.length;X++)Math.abs(O[X])===Z&&(M[X]=d,(O[X]<0||Object.is(O[X],-0))&&(e[X]=!0),d*=N[X+1]);let b=NVUtilities.range(0,N[1]-1,1);e[0]&&(b=NVUtilities.range(N[1]-1,0,-1));for(let Z=0;Z<N[1];Z++)b[Z]*=M[0];let z=NVUtilities.range(0,N[2]-1,1);e[1]&&(z=NVUtilities.range(N[2]-1,0,-1));for(let Z=0;Z<N[2];Z++)z[Z]*=M[1];let W=NVUtilities.range(0,N[3]-1,1);e[2]&&(W=NVUtilities.range(N[3]-1,0,-1));for(let Z=0;Z<N[3];Z++)W[Z]*=M[2];const s0=new Uint8Array(this.drawBitmap),K=new Uint8Array(N[1]*N[2]*N[3]);let J=0;for(let Z=0;Z<N[3];Z++)for(let X=0;X<N[2];X++)for(let r0=0;r0<N[1];r0++)K[J]=s0[b[r0]+z[X]+W[Z]],J++;return log.debug("saving drawing"),this.volumes[0].saveToDisk(g,K)}}return log.debug("saving image"),this.volumes[w].saveToDisk(g)}getMeshIndexByID(u){if(typeof u=="number")return u>=this.meshes.length?-1:u;const h=this.meshes.length;for(let g=0;g<h;g++)if(this.meshes[g].id===u)return g;return-1}setMeshProperty(u,h,g){const v=this.getMeshIndexByID(u);if(v<0){log.warn("setMeshProperty() id not loaded",u);return}this.meshes[v].setProperty(h,g,this.gl),this.updateGLVolume(),this.onMeshPropertyChanged(v,h,g)}indexNearestXYZmm(u,h,g,v){const w=this.getMeshIndexByID(u);return w<0?(log.warn("indexNearestXYZmm() id not loaded",u),[NaN,NaN]):this.meshes[w].indexNearestXYZmm(h,g,v)}reverseFaces(u){const h=this.getMeshIndexByID(u);if(h<0){log.warn("reverseFaces() id not loaded",u);return}this.meshes[h].reverseFaces(this.gl),this.updateGLVolume()}setMeshLayerProperty(u,h,g,v){const w=this.getMeshIndexByID(u);if(w<0){log.warn("setMeshLayerProperty() id not loaded",u);return}this.meshes[w].setLayerProperty(h,g,v,this.gl),this.updateGLVolume()}setPan2Dxyzmm(u){this.scene.pan2Dxyzmm=u,this.opts.yoke3Dto2DZoom&&(this.scene.volScaleMultiplier=u[3]),this.drawScene()}setRenderAzimuthElevation(u,h){this.scene.renderAzimuth=u,this.scene.renderElevation=h,this.onAzimuthElevationChange(u,h),this.drawScene()}getOverlayIndexByID(u){const h=this.overlays.length;for(let g=0;g<h;g++)if(this.overlays[g].id===u)return g;return-1}setVolume(u,h=0){const g=this.volumes.length;if(h>g)return;const v=this.getVolumeIndexByID(u.id);h===0?(this.volumes.splice(v,1),this.volumes.unshift(u),this.back=this.volumes[0],this.overlays=this.volumes.slice(1)):h<0?(this.volumes.splice(this.getVolumeIndexByID(u.id),1),this.back=this.volumes[0],this.volumes.length>1?this.overlays=this.volumes.slice(1):this.overlays=[]):(this.volumes.splice(v,1),this.volumes.splice(h,0,u),this.overlays=this.volumes.slice(1),this.back=this.volumes[0]),this.updateGLVolume()}setMesh(u,h=0){this.meshes.forEach(w=>{log.debug("MESH: ",w.name)});const g=this.meshes.length;if(h>g)return;const v=this.getMeshIndexByID(u.id);h===0?(this.meshes.splice(v,1),this.meshes.unshift(u)):h<0?this.meshes.splice(this.getMeshIndexByID(u.id),1):(this.meshes.splice(v,1),this.meshes.splice(h,0,u)),this.updateGLVolume(),this.meshes.forEach(w=>{log.debug(w.name)})}removeVolume(u){if(this.setVolume(u,-1),this.mediaUrlMap.has(u)){const h=this.mediaUrlMap.get(u);this.onVolumeWithUrlRemoved(h),this.mediaUrlMap.delete(u)}this.drawScene()}removeVolumeByIndex(u){if(u>=this.volumes.length)throw new Error("Index of volume out of bounds");this.removeVolume(this.volumes[u])}removeMesh(u){if(this.setMesh(u,-1),this.mediaUrlMap.has(u)){const h=this.mediaUrlMap.get(u);this.onMeshWithUrlRemoved(h),this.mediaUrlMap.delete(u)}}removeMeshByUrl(u){const h=this.getMediaByUrl(u);h&&(this.removeMesh(h),this.mediaUrlMap.delete(h),this.onMeshWithUrlRemoved(u))}moveVolumeToBottom(u){this.setVolume(u,0)}moveVolumeUp(u){const h=this.getVolumeIndexByID(u.id);this.setVolume(u,h+1)}moveVolumeDown(u){const h=this.getVolumeIndexByID(u.id);this.setVolume(u,h-1)}moveVolumeToTop(u){this.setVolume(u,this.volumes.length-1)}mouseDown(u,h){u*=this.uiData.dpr,h*=this.uiData.dpr,this.mousePos=[u,h]}mouseMove(u,h){u*=this.uiData.dpr,h*=this.uiData.dpr;const g=(u-this.mousePos[0])/this.uiData.dpr,v=(h-this.mousePos[1])/this.uiData.dpr;this.mousePos=[u,h],!(this.inRenderTile(u,h)<0)&&(Math.abs(g)<1&&Math.abs(v)<1||(this.scene.renderAzimuth+=g,this.scene.renderElevation+=v,this.drawScene()))}sph2cartDeg(u,h){const g=-h*(Math.PI/180),v=(u-90)%360*(Math.PI/180),w=[Math.cos(g)*Math.cos(v),Math.cos(g)*Math.sin(v),Math.sin(g)],C=Math.sqrt(w[0]*w[0]+w[1]*w[1]+w[2]*w[2]);return C<=0||(w[0]/=C,w[1]/=C,w[2]/=C),w}setClipPlane(u){const h=this.sph2cartDeg(u[1]+180,u[2]);this.scene.clipPlane=[h[0],h[1],h[2],u[0]],this.scene.clipPlaneDepthAziElev=u,this.onClipPlaneChange(this.scene.clipPlane),this.drawScene()}setCrosshairColor(u){this.opts.crosshairColor=u,this.drawScene()}setCrosshairWidth(u){this.opts.crosshairWidth=u,this.crosshairs3D&&(this.crosshairs3D.mm[0]=NaN),this.drawScene()}setDrawColormap(u){this.drawLut=cmapper.makeDrawLut(u),this.updateGLVolume()}setDrawingEnabled(u){this.opts.drawingEnabled=u,this.opts.drawingEnabled&&(this.drawBitmap||this.createEmptyDrawing()),this.drawScene()}setPenValue(u,h=!1){this.opts.penValue=u,this.opts.isFilledPen=h,this.drawScene()}setDrawOpacity(u){this.drawOpacity=u,this.drawScene()}setSelectionBoxColor(u){this.opts.selectionBoxColor=u}sliceScroll2D(u,h,g,v=!0){if(this.inGraphTile(h,g)){let w=this.volumes[0].frame4D;u>0&&w++,u<0&&w--,this.setFrame4D(this.volumes[0].id,w);return}if(u!==0&&this.opts.dragMode===DRAG_MODE.pan&&this.inRenderTile(this.uiData.dpr*h,this.uiData.dpr*g)===-1){let w=this.scene.pan2Dxyzmm[3]*(1+10*u);w=Math.round(w*10)/10;const C=this.scene.pan2Dxyzmm[3]-w;this.opts.yoke3Dto2DZoom&&(this.scene.volScaleMultiplier=w),this.scene.pan2Dxyzmm[3]=w;const k=this.frac2mm(this.scene.crosshairPos);this.scene.pan2Dxyzmm[0]+=C*k[0],this.scene.pan2Dxyzmm[1]+=C*k[1],this.scene.pan2Dxyzmm[2]+=C*k[2],this.drawScene();return}this.mouseClick(h,g,u,v)}setSliceType(u){return this.opts.sliceType=u,this.drawScene(),this}setOpacity(u,h){if(this.volumes[u].opacity=h,u===0){this.drawScene();return}this.updateGLVolume()}setScale(u){this.scene.volScaleMultiplier=u,this.drawScene()}setClipPlaneColor(u){this.opts.clipPlaneColor=u,this.renderShader.use(this.gl),this.gl.uniform4fv(this.renderShader.uniforms.clipPlaneColor,this.opts.clipPlaneColor),this.drawScene()}async setVolumeRenderIllumination(u=0){this.renderShader=this.renderVolumeShader,u>0&&(this.renderShader=this.renderGradientShader),u<0&&(this.renderShader=this.renderSliceShader),this.initRenderShader(this.renderShader,u),this.renderShader.use(this.gl),this.setClipPlaneColor(this.opts.clipPlaneColor),this.gradientTextureAmount=u,this.refreshLayers(this.volumes[0],0),this.drawScene()}overlayRGBA(u){const h=u.hdr,g=h.dims[1]*h.dims[2]*h.dims[3],v=new Uint8ClampedArray(g*4),w=.2*Math.min(Math.min(h.dims[1],h.dims[2]),h.dims[3]),C=.5*h.dims[1],k=.5*h.dims[2],U=.5*h.dims[3];let N=0;for(let O=0;O<h.dims[3];O++)for(let d=0;d<h.dims[2];d++)for(let M=0;M<h.dims[1];M++){const e=Math.abs(M-C),b=Math.abs(d-k),z=Math.abs(O-U),W=Math.sqrt(e*e+b*b+z*z);let s0=0;W<w&&(s0=255),v[N++]=0,v[N++]=s0,v[N++]=0,v[N++]=s0*.5}return v}vox2mm(u,h){return NVUtilities.vox2mm(u,h)}cloneVolume(u){return this.volumes[u].clone()}async loadDocumentFromUrl(u){const h=await NVDocument.loadFromUrl(u);this.loadDocument(h)}loadDocument(u){this.volumes=[],this.meshes=[],this.document=u,this.document.labels=this.document.labels?this.document.labels:[];const h={...DEFAULT_OPTIONS,...u.opts};this.scene.pan2Dxyzmm=u.scene.pan2Dxyzmm?u.scene.pan2Dxyzmm:[0,0,0,1],this.document.opts=h,this.setClipPlane(this.scene.clipPlaneDepthAziElev),log.debug("load document",u),this.mediaUrlMap.clear(),this.createEmptyDrawing();const g=u.encodedImageBlobs;for(let w=0;w<u.imageOptionsArray.length;w++){const C=u.imageOptionsArray[w],k=g[w];if(k){"colorMap"in C&&(C.colormap=C.colorMap);const U=NVImage.loadFromBase64({base64:k,...C});U&&this.addVolume(U)}}this.volumes.length>0&&(this.back=this.volumes[0]);const v=u.encodedDrawingBlob;if(v){const w=u.imageOptionsArray[0],C=NVImage.loadFromBase64({base64:v,...w});C&&this.loadDrawing(C)}for(const w of u.meshDataObjects??[]){const C={gl:this.gl,...w};log.debug(C);const k=new NVMesh(C.pts,C.tris,C.name,C.rgba255,C.opacity,C.visible,this.gl,C.connectome,C.dpg,C.dps,C.dpv);k.meshShaderIndex=C.meshShaderIndex,k.layers=C.layers,k.updateMesh(this.gl),log.debug(k),this.addMesh(k)}if(u.data.connectomes)for(const w of u.data.connectomes){const C=JSON.parse(w),k=this.loadConnectomeAsMesh(C);k.updateMesh(this.gl),this.addMesh(k)}return this.updateGLVolume(),this.drawScene(),this.onDocumentLoaded(u),this}generateLoadDocumentJavaScript(u,h){const g=this.json(),v=NVUtilities.compressToBase64String(JSON.stringify(g));return`
1616
+ `):"",this.name="UnsubscriptionError",this.errors=h}});function arrRemove(T,u){if(T){var h=T.indexOf(u);0<=h&&T.splice(h,1)}}var Subscription=function(){function T(u){this.initialTeardown=u,this.closed=!1,this._parentage=null,this._finalizers=null}return T.prototype.unsubscribe=function(){var u,h,g,v,w;if(!this.closed){this.closed=!0;var C=this._parentage;if(C)if(this._parentage=null,Array.isArray(C))try{for(var k=__values(C),U=k.next();!U.done;U=k.next()){var N=U.value;N.remove(this)}}catch(z){u={error:z}}finally{try{U&&!U.done&&(h=k.return)&&h.call(k)}finally{if(u)throw u.error}}else C.remove(this);var O=this.initialTeardown;if(isFunction(O))try{O()}catch(z){w=z instanceof UnsubscriptionError?z.errors:[z]}var d=this._finalizers;if(d){this._finalizers=null;try{for(var M=__values(d),e=M.next();!e.done;e=M.next()){var b=e.value;try{execFinalizer(b)}catch(z){w=w??[],z instanceof UnsubscriptionError?w=__spreadArray(__spreadArray([],__read(w)),__read(z.errors)):w.push(z)}}}catch(z){g={error:z}}finally{try{e&&!e.done&&(v=M.return)&&v.call(M)}finally{if(g)throw g.error}}}if(w)throw new UnsubscriptionError(w)}},T.prototype.add=function(u){var h;if(u&&u!==this)if(this.closed)execFinalizer(u);else{if(u instanceof T){if(u.closed||u._hasParent(this))return;u._addParent(this)}(this._finalizers=(h=this._finalizers)!==null&&h!==void 0?h:[]).push(u)}},T.prototype._hasParent=function(u){var h=this._parentage;return h===u||Array.isArray(h)&&h.includes(u)},T.prototype._addParent=function(u){var h=this._parentage;this._parentage=Array.isArray(h)?(h.push(u),h):h?[h,u]:u},T.prototype._removeParent=function(u){var h=this._parentage;h===u?this._parentage=null:Array.isArray(h)&&arrRemove(h,u)},T.prototype.remove=function(u){var h=this._finalizers;h&&arrRemove(h,u),u instanceof T&&u._removeParent(this)},T.EMPTY=function(){var u=new T;return u.closed=!0,u}(),T}(),EMPTY_SUBSCRIPTION=Subscription.EMPTY;function isSubscription(T){return T instanceof Subscription||T&&"closed"in T&&isFunction(T.remove)&&isFunction(T.add)&&isFunction(T.unsubscribe)}function execFinalizer(T){isFunction(T)?T():T.unsubscribe()}var config={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1},timeoutProvider={setTimeout:function(T,u){for(var h=[],g=2;g<arguments.length;g++)h[g-2]=arguments[g];return setTimeout.apply(void 0,__spreadArray([T,u],__read(h)))},clearTimeout:function(T){var u=timeoutProvider.delegate;return((u==null?void 0:u.clearTimeout)||clearTimeout)(T)},delegate:void 0};function reportUnhandledError(T){timeoutProvider.setTimeout(function(){throw T})}function noop(){}function errorContext(T){T()}var Subscriber=function(T){__extends(u,T);function u(h){var g=T.call(this)||this;return g.isStopped=!1,h?(g.destination=h,isSubscription(h)&&h.add(g)):g.destination=EMPTY_OBSERVER,g}return u.create=function(h,g,v){return new SafeSubscriber(h,g,v)},u.prototype.next=function(h){this.isStopped||this._next(h)},u.prototype.error=function(h){this.isStopped||(this.isStopped=!0,this._error(h))},u.prototype.complete=function(){this.isStopped||(this.isStopped=!0,this._complete())},u.prototype.unsubscribe=function(){this.closed||(this.isStopped=!0,T.prototype.unsubscribe.call(this),this.destination=null)},u.prototype._next=function(h){this.destination.next(h)},u.prototype._error=function(h){try{this.destination.error(h)}finally{this.unsubscribe()}},u.prototype._complete=function(){try{this.destination.complete()}finally{this.unsubscribe()}},u}(Subscription),_bind=Function.prototype.bind;function bind(T,u){return _bind.call(T,u)}var ConsumerObserver=function(){function T(u){this.partialObserver=u}return T.prototype.next=function(u){var h=this.partialObserver;if(h.next)try{h.next(u)}catch(g){handleUnhandledError(g)}},T.prototype.error=function(u){var h=this.partialObserver;if(h.error)try{h.error(u)}catch(g){handleUnhandledError(g)}else handleUnhandledError(u)},T.prototype.complete=function(){var u=this.partialObserver;if(u.complete)try{u.complete()}catch(h){handleUnhandledError(h)}},T}(),SafeSubscriber=function(T){__extends(u,T);function u(h,g,v){var w=T.call(this)||this,C;if(isFunction(h)||!h)C={next:h??void 0,error:g??void 0,complete:v??void 0};else{var k;w&&config.useDeprecatedNextContext?(k=Object.create(h),k.unsubscribe=function(){return w.unsubscribe()},C={next:h.next&&bind(h.next,k),error:h.error&&bind(h.error,k),complete:h.complete&&bind(h.complete,k)}):C=h}return w.destination=new ConsumerObserver(C),w}return u}(Subscriber);function handleUnhandledError(T){reportUnhandledError(T)}function defaultErrorHandler(T){throw T}var EMPTY_OBSERVER={closed:!0,next:noop,error:defaultErrorHandler,complete:noop},observable=function(){return typeof Symbol=="function"&&Symbol.observable||"@@observable"}();function identity(T){return T}function pipeFromArray(T){return T.length===0?identity:T.length===1?T[0]:function(h){return T.reduce(function(g,v){return v(g)},h)}}var Observable=function(){function T(u){u&&(this._subscribe=u)}return T.prototype.lift=function(u){var h=new T;return h.source=this,h.operator=u,h},T.prototype.subscribe=function(u,h,g){var v=this,w=isSubscriber(u)?u:new SafeSubscriber(u,h,g);return errorContext(function(){var C=v,k=C.operator,U=C.source;w.add(k?k.call(w,U):U?v._subscribe(w):v._trySubscribe(w))}),w},T.prototype._trySubscribe=function(u){try{return this._subscribe(u)}catch(h){u.error(h)}},T.prototype.forEach=function(u,h){var g=this;return h=getPromiseCtor(h),new h(function(v,w){var C=new SafeSubscriber({next:function(k){try{u(k)}catch(U){w(U),C.unsubscribe()}},error:w,complete:v});g.subscribe(C)})},T.prototype._subscribe=function(u){var h;return(h=this.source)===null||h===void 0?void 0:h.subscribe(u)},T.prototype[observable]=function(){return this},T.prototype.pipe=function(){for(var u=[],h=0;h<arguments.length;h++)u[h]=arguments[h];return pipeFromArray(u)(this)},T.prototype.toPromise=function(u){var h=this;return u=getPromiseCtor(u),new u(function(g,v){var w;h.subscribe(function(C){return w=C},function(C){return v(C)},function(){return g(w)})})},T.create=function(u){return new T(u)},T}();function getPromiseCtor(T){var u;return(u=T??config.Promise)!==null&&u!==void 0?u:Promise}function isObserver(T){return T&&isFunction(T.next)&&isFunction(T.error)&&isFunction(T.complete)}function isSubscriber(T){return T&&T instanceof Subscriber||isObserver(T)&&isSubscription(T)}var ObjectUnsubscribedError=createErrorClass(function(T){return function(){T(this),this.name="ObjectUnsubscribedError",this.message="object unsubscribed"}}),Subject=function(T){__extends(u,T);function u(){var h=T.call(this)||this;return h.closed=!1,h.currentObservers=null,h.observers=[],h.isStopped=!1,h.hasError=!1,h.thrownError=null,h}return u.prototype.lift=function(h){var g=new AnonymousSubject(this,this);return g.operator=h,g},u.prototype._throwIfClosed=function(){if(this.closed)throw new ObjectUnsubscribedError},u.prototype.next=function(h){var g=this;errorContext(function(){var v,w;if(g._throwIfClosed(),!g.isStopped){g.currentObservers||(g.currentObservers=Array.from(g.observers));try{for(var C=__values(g.currentObservers),k=C.next();!k.done;k=C.next()){var U=k.value;U.next(h)}}catch(N){v={error:N}}finally{try{k&&!k.done&&(w=C.return)&&w.call(C)}finally{if(v)throw v.error}}}})},u.prototype.error=function(h){var g=this;errorContext(function(){if(g._throwIfClosed(),!g.isStopped){g.hasError=g.isStopped=!0,g.thrownError=h;for(var v=g.observers;v.length;)v.shift().error(h)}})},u.prototype.complete=function(){var h=this;errorContext(function(){if(h._throwIfClosed(),!h.isStopped){h.isStopped=!0;for(var g=h.observers;g.length;)g.shift().complete()}})},u.prototype.unsubscribe=function(){this.isStopped=this.closed=!0,this.observers=this.currentObservers=null},Object.defineProperty(u.prototype,"observed",{get:function(){var h;return((h=this.observers)===null||h===void 0?void 0:h.length)>0},enumerable:!1,configurable:!0}),u.prototype._trySubscribe=function(h){return this._throwIfClosed(),T.prototype._trySubscribe.call(this,h)},u.prototype._subscribe=function(h){return this._throwIfClosed(),this._checkFinalizedStatuses(h),this._innerSubscribe(h)},u.prototype._innerSubscribe=function(h){var g=this,v=this,w=v.hasError,C=v.isStopped,k=v.observers;return w||C?EMPTY_SUBSCRIPTION:(this.currentObservers=null,k.push(h),new Subscription(function(){g.currentObservers=null,arrRemove(k,h)}))},u.prototype._checkFinalizedStatuses=function(h){var g=this,v=g.hasError,w=g.thrownError,C=g.isStopped;v?h.error(w):C&&h.complete()},u.prototype.asObservable=function(){var h=new Observable;return h.source=this,h},u.create=function(h,g){return new AnonymousSubject(h,g)},u}(Observable),AnonymousSubject=function(T){__extends(u,T);function u(h,g){var v=T.call(this)||this;return v.destination=h,v.source=g,v}return u.prototype.next=function(h){var g,v;(v=(g=this.destination)===null||g===void 0?void 0:g.next)===null||v===void 0||v.call(g,h)},u.prototype.error=function(h){var g,v;(v=(g=this.destination)===null||g===void 0?void 0:g.error)===null||v===void 0||v.call(g,h)},u.prototype.complete=function(){var h,g;(g=(h=this.destination)===null||h===void 0?void 0:h.complete)===null||g===void 0||g.call(h)},u.prototype._subscribe=function(h){var g,v;return(v=(g=this.source)===null||g===void 0?void 0:g.subscribe(h))!==null&&v!==void 0?v:EMPTY_SUBSCRIPTION},u}(Subject),dateTimestampProvider={now:function(){return(dateTimestampProvider.delegate||Date).now()},delegate:void 0},ReplaySubject=function(T){__extends(u,T);function u(h,g,v){h===void 0&&(h=1/0),g===void 0&&(g=1/0),v===void 0&&(v=dateTimestampProvider);var w=T.call(this)||this;return w._bufferSize=h,w._windowTime=g,w._timestampProvider=v,w._buffer=[],w._infiniteTimeWindow=!0,w._infiniteTimeWindow=g===1/0,w._bufferSize=Math.max(1,h),w._windowTime=Math.max(1,g),w}return u.prototype.next=function(h){var g=this,v=g.isStopped,w=g._buffer,C=g._infiniteTimeWindow,k=g._timestampProvider,U=g._windowTime;v||(w.push(h),!C&&w.push(k.now()+U)),this._trimBuffer(),T.prototype.next.call(this,h)},u.prototype._subscribe=function(h){this._throwIfClosed(),this._trimBuffer();for(var g=this._innerSubscribe(h),v=this,w=v._infiniteTimeWindow,C=v._buffer,k=C.slice(),U=0;U<k.length&&!h.closed;U+=w?1:2)h.next(k[U]);return this._checkFinalizedStatuses(h),g},u.prototype._trimBuffer=function(){var h=this,g=h._bufferSize,v=h._timestampProvider,w=h._buffer,C=h._infiniteTimeWindow,k=(C?1:2)*g;if(g<1/0&&k<w.length&&w.splice(0,w.length-k),!C){for(var U=v.now(),N=0,O=1;O<w.length&&w[O]<=U;O+=2)N=O;N&&w.splice(0,N+1)}},u}(Subject),DEFAULT_WEBSOCKET_CONFIG={url:"",deserializer:function(T){return JSON.parse(T.data)},serializer:function(T){return JSON.stringify(T)}},WEBSOCKETSUBJECT_INVALID_ERROR_OBJECT="WebSocketSubject.error must be called with an object with an error code, and an optional reason: { code: number, reason: string }",WebSocketSubject=function(T){__extends(u,T);function u(h,g){var v=T.call(this)||this;if(v._socket=null,h instanceof Observable)v.destination=g,v.source=h;else{var w=v._config=__assign({},DEFAULT_WEBSOCKET_CONFIG);if(v._output=new Subject,typeof h=="string")w.url=h;else for(var C in h)h.hasOwnProperty(C)&&(w[C]=h[C]);if(!w.WebSocketCtor&&WebSocket)w.WebSocketCtor=WebSocket;else if(!w.WebSocketCtor)throw new Error("no WebSocket constructor can be found");v.destination=new ReplaySubject}return v}return u.prototype.lift=function(h){var g=new u(this._config,this.destination);return g.operator=h,g.source=this,g},u.prototype._resetState=function(){this._socket=null,this.source||(this.destination=new ReplaySubject),this._output=new Subject},u.prototype.multiplex=function(h,g,v){var w=this;return new Observable(function(C){try{w.next(h())}catch(U){C.error(U)}var k=w.subscribe({next:function(U){try{v(U)&&C.next(U)}catch(N){C.error(N)}},error:function(U){return C.error(U)},complete:function(){return C.complete()}});return function(){try{w.next(g())}catch(U){C.error(U)}k.unsubscribe()}})},u.prototype._connectSocket=function(){var h=this,g=this._config,v=g.WebSocketCtor,w=g.protocol,C=g.url,k=g.binaryType,U=this._output,N=null;try{N=w?new v(C,w):new v(C),this._socket=N,k&&(this._socket.binaryType=k)}catch(d){U.error(d);return}var O=new Subscription(function(){h._socket=null,N&&N.readyState===1&&N.close()});N.onopen=function(d){var M=h._socket;if(!M){N.close(),h._resetState();return}var e=h._config.openObserver;e&&e.next(d);var b=h.destination;h.destination=Subscriber.create(function(z){if(N.readyState===1)try{var W=h._config.serializer;N.send(W(z))}catch(s0){h.destination.error(s0)}},function(z){var W=h._config.closingObserver;W&&W.next(void 0),z&&z.code?N.close(z.code,z.reason):U.error(new TypeError(WEBSOCKETSUBJECT_INVALID_ERROR_OBJECT)),h._resetState()},function(){var z=h._config.closingObserver;z&&z.next(void 0),N.close(),h._resetState()}),b&&b instanceof ReplaySubject&&O.add(b.subscribe(h.destination))},N.onerror=function(d){h._resetState(),U.error(d)},N.onclose=function(d){N===h._socket&&h._resetState();var M=h._config.closeObserver;M&&M.next(d),d.wasClean?U.complete():U.error(d)},N.onmessage=function(d){try{var M=h._config.deserializer;U.next(M(d))}catch(e){U.error(e)}}},u.prototype._subscribe=function(h){var g=this,v=this.source;return v?v.subscribe(h):(this._socket||this._connectSocket(),this._output.subscribe(h),h.add(function(){var w=g._socket;g._output.observers.length===0&&(w&&(w.readyState===1||w.readyState===0)&&w.close(),g._resetState())}),h)},u.prototype.unsubscribe=function(){var h=this._socket;h&&(h.readyState===1||h.readyState===0)&&h.close(),this._resetState(),T.prototype.unsubscribe.call(this)},u}(AnonymousSubject);function webSocket(T){return new WebSocketSubject(T)}var NVMESSAGE=(T=>(T[T.ZOOM=1]="ZOOM",T[T.CLIP_PLANE=2]="CLIP_PLANE",T[T.AZIMUTH_ELEVATION=3]="AZIMUTH_ELEVATION",T[T.FRAME_CHANGED=4]="FRAME_CHANGED",T[T.VOLUME_ADDED_FROM_URL=5]="VOLUME_ADDED_FROM_URL",T[T.VOLUME_WITH_URL_REMOVED=6]="VOLUME_WITH_URL_REMOVED",T[T.COLORMAP_CHANGED=7]="COLORMAP_CHANGED",T[T.OPACITY_CHANGED=8]="OPACITY_CHANGED",T[T.MESH_FROM_URL_ADDED=9]="MESH_FROM_URL_ADDED",T[T.MESH_WITH_URL_REMOVED=10]="MESH_WITH_URL_REMOVED",T[T.CUSTOM_SHADER_ADDED=11]="CUSTOM_SHADER_ADDED",T[T.SHADER_CHANGED=12]="SHADER_CHANGED",T[T.MESH_PROPERTY_CHANGED=13]="MESH_PROPERTY_CHANGED",T.USER_JOINED="user joined",T.CREATE="create",T.VOLUME_LOADED_FROM_URL="volume with url added",T))(NVMESSAGE||{});class SessionUser{constructor(u,h,g,v){g0(this,"id");g0(this,"displayName");g0(this,"key");g0(this,"properties");this.id=h||v4(),this.displayName=u||`user-${this.id}`,this.key=g||v4(),this.properties=v||new Map}}function storageAvailable(T){const u=window[T],h="test";try{return u.setItem(h,h),u.removeItem(h),!0}catch{return!1}}class SessionBus{constructor(u,h,g,v="",w=""){g0(this,"userList");g0(this,"user");g0(this,"userQueueName");g0(this,"userListName");g0(this,"onMessageCallback");g0(this,"isConnectedToServer",!1);g0(this,"isController",!1);g0(this,"sessionScene",{});g0(this,"sessionKey");g0(this,"sessionName");g0(this,"sessionSceneName");g0(this,"serverConnection$",null);if(this.userList=[],this.user=h||new SessionUser("anonymous"),this.onMessageCallback=g,this.sessionScene={},this.sessionKey=w||v4(),this.sessionName=u,this.sessionSceneName=`session-${u}-scene`,v)this.connectToServer(v,u),this.subscribeToServer(),this.isConnectedToServer=!0,this.serverConnection$!==null&&this.serverConnection$.next({op:NVMESSAGE.CREATE,key:this.sessionKey});else{if(!storageAvailable("localStorage"))throw new Error("Local storage unavailable");this.userQueueName=`user-${this.user.id}-q`,this.userListName=`${u}-user-list`,this.userList=JSON.parse(localStorage.getItem(this.userListName)||"[]"),this.userList.push(this.user),localStorage.setItem(this.userListName,JSON.stringify(this.userList)),localStorage.setItem(this.userQueueName,JSON.stringify([])),window.addEventListener("storage",this.localStorageEventListener.bind(this))}}sendSessionMessage(u){u.from=this.user.id,this.isConnectedToServer&&this.serverConnection$!==null?this.serverConnection$.next({...u,key:this.sessionKey,userKey:this.user.key}):this.sendLocalMessage(u)}connectToServer(u,h){const g=new URL(u);g.pathname="websockets",g.search="?session="+h,this.serverConnection$=webSocket(g.href),log.debug(g.href)}subscribeToServer(){this.serverConnection$!==null&&this.serverConnection$.subscribe({next:u=>{this.onMessageCallback(u)},error:u=>log.error(u),complete:()=>log.debug("complete")})}sendLocalMessage(u){for(const h of this.userList){if(h.id===this.user.id)continue;const g=`user-${h.id}-q`,v=localStorage.getItem(g),w=v?JSON.parse(v):[];w.push(u),localStorage.setItem(g,JSON.stringify(w))}}localStorageEventListener(u){if(u.newValue)switch(u.key){case this.userListName:{const h=JSON.parse(u.newValue),g=JSON.parse(u.oldValue??"[]");this.userList=h;const v=h.filter(w=>!g.map(C=>C.id).includes(w.id));for(const w of v)this.onMessageCallback({op:NVMESSAGE.USER_JOINED,user:w})}break;case this.userQueueName:{const h=JSON.parse(u.newValue);for(const g of h)this.onMessageCallback&&this.onMessageCallback(g);localStorage.setItem(this.userQueueName??"",JSON.stringify([]))}break}}}class NVController{constructor(u){g0(this,"niivue");g0(this,"mediaUrlMap");g0(this,"isInSession",!1);g0(this,"user");g0(this,"sessionBus");g0(this,"onFrameChange",(u,h)=>{});this.niivue=u,this.mediaUrlMap=new Map,this.niivue.onLocationChange=this.onLocationChangeHandler.bind(this),this.niivue.onZoom3DChange=this.onZoom3DChangeHandler.bind(this),this.niivue.scene.onAzimuthElevationChange=this.onAzimuthElevationChangeHandler.bind(this),this.niivue.onClipPlaneChange=this.onClipPlaneChangeHandler.bind(this),this.niivue.onVolumeAddedFromUrl=this.onVolumeAddedFromUrlHandler.bind(this),this.niivue.onVolumeWithUrlRemoved=this.onVolumeWithUrlRemovedHandler.bind(this),this.niivue.onMeshAddedFromUrl=this.onMeshAddedFromUrlHandler.bind(this),this.niivue.onMeshWithUrlRemoved=this.onMeshWithUrlRemovedHandler.bind(this),this.niivue.onCustomMeshShaderAdded=this.onCustomMeshShaderAddedHandler.bind(this),this.niivue.onMeshShaderChanged=this.onMeshShaderChanged.bind(this),this.niivue.onMeshPropertyChanged=this.onMeshPropertyChanged.bind(this),this.niivue.onFrameChange=this.onFrameChangeHandler.bind(this);for(const h of this.niivue.volumes)h.onColormapChange=this.onColormapChangeHandler.bind(this),h.onOpacityChange=this.onOpacityChangeHandler.bind(this)}onLocationChangeHandler(u){log.debug(u)}addVolume(u,h){this.niivue.volumes.push(u);const g=this.niivue.volumes.length===1?0:this.niivue.volumes.length-1;this.niivue.setVolume(u,g),this.niivue.mediaUrlMap.set(u,h)}addMesh(u,h){this.niivue.meshes.push(u);const g=this.niivue.meshes.length===1?0:this.niivue.meshes.length-1;this.niivue.setMesh(u,g),this.niivue.mediaUrlMap.set(u,h)}onNewMessage(u){switch(u.op){case NVMESSAGE.ZOOM:this.niivue.volScaleMultiplier=u.zoom;break;case NVMESSAGE.CLIP_PLANE:this.niivue.scene.clipPlane=u.clipPlane;break;case NVMESSAGE.AZIMUTH_ELEVATION:this.niivue.scene._elevation=u.elevation,this.niivue.scene._azimuth=u.azimuth;break;case NVMESSAGE.FRAME_CHANGED:{const h=this.niivue.getMediaByUrl(u.url);h&&(h.frame4D=u.index)}break;case NVMESSAGE.VOLUME_ADDED_FROM_URL:this.niivue.getMediaByUrl(u.imageOptions.url)||NVImage.loadFromUrl(u.imageOptions).then(h=>{h&&this.addVolume(h,u.imageOptions.url)}).catch(h=>{if(h)throw h});break;case NVMESSAGE.VOLUME_WITH_URL_REMOVED:{const h=this.niivue.getMediaByUrl(u.url);h&&(this.niivue.setVolume(h,-1),this.niivue.mediaUrlMap.delete(h))}break;case NVMESSAGE.COLORMAP_CHANGED:{const h=this.niivue.getMediaByUrl(u.url);h._colormap=u.colormap,this.niivue.updateGLVolume()}break;case NVMESSAGE.OPACITY_CHANGED:{const h=this.niivue.getMediaByUrl(u.url);h._opacity=u.opacity,this.niivue.updateGLVolume()}break;case NVMESSAGE.MESH_FROM_URL_ADDED:this.niivue.getMediaByUrl(u.meshOptions.url)||(u.meshOptions.gl=this.niivue.gl,NVMesh.loadFromUrl(u.meshOptions).then(h=>{this.addMesh(h,u.meshOptions.url)}).catch(h=>{if(h)throw h}));break;case NVMESSAGE.MESH_WITH_URL_REMOVED:{const h=this.niivue.getMediaByUrl(u.url);h&&(this.niivue.setMesh(h,-1),this.niivue.mediaUrlMap.delete(h))}break;case NVMESSAGE.CUSTOM_SHADER_ADDED:{const h=this.niivue.createCustomMeshShader(u.fragmentShaderText,u.name);this.niivue.meshShaders.push(h)}break;case NVMESSAGE.SHADER_CHANGED:this.niivue.meshes[u.meshIndex].meshShaderIndex=u.shaderIndex,this.niivue.updateGLVolume();break;case NVMESSAGE.MESH_PROPERTY_CHANGED:this.niivue.meshes[u.meshIndex].setProperty(u.key,u.val,this.niivue.gl);break}this.niivue.drawScene()}connectToSession(u,h,g,v){this.user=h||new SessionUser,this.sessionBus=new SessionBus(u,this.user,this.onNewMessage.bind(this),g,v),this.isInSession=!0}onZoom3DChangeHandler(u){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.ZOOM,zoom:u})}onAzimuthElevationChangeHandler(u,h){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.AZIMUTH_ELEVATION,azimuth:u,elevation:h})}onClipPlaneChangeHandler(u){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.CLIP_PLANE,clipPlane:u})}onVolumeAddedFromUrlHandler(u,h){this.isInSession&&this.sessionBus&&(log.debug(u),this.sessionBus.sendSessionMessage({op:NVMESSAGE.VOLUME_ADDED_FROM_URL,imageOptions:u})),h.onColormapChange=this.onColormapChangeHandler.bind(this),h.onOpacityChange=this.onOpacityChangeHandler.bind(this)}onImageLoadedHandler(u){if(u.onColormapChange=this.onColormapChangeHandler.bind(this),u.onOpacityChange=this.onOpacityChangeHandler.bind(this),this.isInSession&&this.sessionBus&&this.niivue.mediaUrlMap.has(u)){const h=this.niivue.mediaUrlMap.get(u);this.sessionBus.sendSessionMessage({op:NVMESSAGE.VOLUME_LOADED_FROM_URL,url:h})}}onVolumeWithUrlRemovedHandler(u){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.VOLUME_WITH_URL_REMOVED,url:u})}onMeshAddedFromUrlHandler(u){log.debug("mesh loaded from url"),log.debug(u),this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.MESH_FROM_URL_ADDED,meshOptions:u})}onMeshLoadedHandler(u){log.debug("mesh has been added"),log.debug(u)}onMeshWithUrlRemovedHandler(u){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.MESH_WITH_URL_REMOVED,url:u})}onColormapChangeHandler(u){if(this.isInSession&&this.sessionBus&&this.niivue.mediaUrlMap.has(u)){const h=this.niivue.mediaUrlMap.get(u),g=u.colormap;this.sessionBus.sendSessionMessage({op:NVMESSAGE.COLORMAP_CHANGED,url:h,colormap:g})}}onOpacityChangeHandler(u){if(this.isInSession&&this.sessionBus&&this.niivue.mediaUrlMap.has(u)){const h=this.niivue.mediaUrlMap.get(u),g=u.opacity;this.sessionBus.sendSessionMessage({op:NVMESSAGE.OPACITY_CHANGED,url:h,opacity:g})}}onFrameChangeHandler(u,h){if(log.debug("frame has changed to "+h),log.debug(u),this.niivue.mediaUrlMap.has(u)&&this.isInSession&&this.sessionBus){const g=this.niivue.mediaUrlMap.get(u);this.sessionBus.sendSessionMessage({op:NVMESSAGE.FRAME_CHANGED,url:g,index:h})}this.onFrameChange(u,h)}onCustomMeshShaderAddedHandler(u,h){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.CUSTOM_SHADER_ADDED,fragmentShaderText:u,name:h})}onMeshShaderChanged(u,h){this.isInSession&&this.sessionBus&&this.sessionBus.sendSessionMessage({op:NVMESSAGE.SHADER_CHANGED,meshIndex:u,shaderIndex:h})}onMeshPropertyChanged(u,h,g){this.isInSession&&this.sessionBus&&(log.debug(NVMESSAGE.MESH_PROPERTY_CHANGED),this.sessionBus.sendSessionMessage({op:NVMESSAGE.MESH_PROPERTY_CHANGED,meshIndex:u,key:h,val:g}))}}const MESH_EXTENSIONS=["ASC","BYU","DFS","FSM","PIAL","ORIG","INFLATED","SMOOTHWM","SPHERE","WHITE","G","GEO","GII","ICO","MZ3","NV","OBJ","OFF","PLY","SRF","STL","TCK","TRACT","TRI","TRK","TT","TRX","VTK","X3D","JCON","JSON"],LEFT_MOUSE_BUTTON=0,CENTER_MOUSE_BUTTON=1,RIGHT_MOUSE_BUTTON=2,TEXTURE0_BACK_VOL=33984,TEXTURE1_COLORMAPS=33985,TEXTURE2_OVERLAY_VOL=33986,TEXTURE3_FONT=33987,TEXTURE4_THUMBNAIL=33988,TEXTURE5_MATCAP=33989,TEXTURE6_GRADIENT=33990,TEXTURE7_DRAW=33991,TEXTURE8_GRADIENT_TEMP=33992,TEXTURE9_ORIENT=33993,TEXTURE10_BLEND=33994,TEXTURE11_GC_BACK=33995,TEXTURE12_GC_STRENGTH0=33996,TEXTURE13_GC_STRENGTH1=33997,TEXTURE14_GC_LABEL0=33998,TEXTURE15_GC_LABEL1=33999,defaultSaveImageOptions={filename:"",isSaveDrawing:!1,volumeByIndex:0};class Niivue{constructor(u=DEFAULT_OPTIONS){g0(this,"canvas",null);g0(this,"_gl",null);g0(this,"isBusy",!1);g0(this,"needsRefresh",!1);g0(this,"colormapTexture",null);g0(this,"colormapLists",[]);g0(this,"volumeTexture",null);g0(this,"gradientTexture",null);g0(this,"gradientTextureAmount",0);g0(this,"drawTexture",null);g0(this,"drawUndoBitmaps",[]);g0(this,"drawLut",cmapper.makeDrawLut("$itksnap"));g0(this,"drawOpacity",.8);g0(this,"renderDrawAmbientOcclusion",.4);g0(this,"colorbarHeight",0);g0(this,"drawPenLocation",[NaN,NaN,NaN]);g0(this,"drawPenAxCorSag",-1);g0(this,"drawFillOverwrites",!0);g0(this,"drawPenFillPts",[]);g0(this,"overlayTexture",null);g0(this,"overlayTextureID",null);g0(this,"sliceMMShader");g0(this,"sliceV1Shader");g0(this,"orientCubeShader");g0(this,"orientCubeShaderVAO",null);g0(this,"rectShader");g0(this,"renderShader");g0(this,"lineShader");g0(this,"line3DShader");g0(this,"passThroughShader");g0(this,"renderGradientShader");g0(this,"renderSliceShader");g0(this,"renderVolumeShader");g0(this,"pickingMeshShader");g0(this,"pickingImageShader");g0(this,"colorbarShader");g0(this,"fontShader",null);g0(this,"fiberShader");g0(this,"fontTexture",null);g0(this,"circleShader");g0(this,"matCapTexture",null);g0(this,"bmpShader",null);g0(this,"bmpTexture",null);g0(this,"thumbnailVisible",!1);g0(this,"bmpTextureWH",1);g0(this,"growCutShader");g0(this,"orientShaderAtlasU",null);g0(this,"orientShaderAtlasI",null);g0(this,"orientShaderU",null);g0(this,"orientShaderI",null);g0(this,"orientShaderF",null);g0(this,"orientShaderRGBU",null);g0(this,"surfaceShader",null);g0(this,"blurShader",null);g0(this,"sobelShader",null);g0(this,"genericVAO",null);g0(this,"unusedVAO",null);g0(this,"crosshairs3D",null);g0(this,"DEFAULT_FONT_GLYPH_SHEET",defaultFontPNG);g0(this,"DEFAULT_FONT_METRICS",defaultFontMetrics);g0(this,"fontMetrics");g0(this,"fontMets",null);g0(this,"backgroundMasksOverlays",0);g0(this,"overlayOutlineWidth",0);g0(this,"overlayAlphaShader",1);g0(this,"isAlphaClipDark",!1);g0(this,"position");g0(this,"extentsMin");g0(this,"extentsMax");g0(this,"resizeObserver",null);g0(this,"syncOpts",{});g0(this,"readyForSync",!1);g0(this,"uiData",{mousedown:!1,touchdown:!1,mouseButtonLeftDown:!1,mouseButtonCenterDown:!1,mouseButtonRightDown:!1,mouseDepthPicker:!1,clickedTile:-1,pan2DxyzmmAtMouseDown:[0,0,0,1],prevX:0,prevY:0,currX:0,currY:0,currentTouchTime:0,lastTouchTime:0,touchTimer:null,doubleTouch:!1,isDragging:!1,dragStart:[0,0],dragEnd:[0,0],dragClipPlaneStartDepthAziElev:[0,0,0],lastTwoTouchDistance:0,multiTouchGesture:!1});g0(this,"back",null);g0(this,"overlays",[]);g0(this,"deferredVolumes",[]);g0(this,"deferredMeshes",[]);g0(this,"furthestVertexFromOrigin",100);g0(this,"volScale",[]);g0(this,"vox",[]);g0(this,"mousePos",[0,0]);g0(this,"screenSlices",[]);g0(this,"cuboidVertexBuffer");g0(this,"otherNV",null);g0(this,"volumeObject3D",null);g0(this,"pivot3D",[0,0,0]);g0(this,"furthestFromPivot",10);g0(this,"currentClipPlaneIndex",0);g0(this,"lastCalled",new Date().getTime());g0(this,"selectedObjectId",-1);g0(this,"CLIP_PLANE_ID",1);g0(this,"VOLUME_ID",254);g0(this,"DISTANCE_FROM_CAMERA",-.54);g0(this,"graph",{LTWH:[0,0,640,480],opacity:0,vols:[0],autoSizeMultiplanar:!1,normalizeValues:!1});g0(this,"meshShaders",[{Name:"Phong",Frag:fragMeshShader},{Name:"Matte",Frag:fragMeshMatteShader},{Name:"Harmonic",Frag:fragMeshShaderSHBlue},{Name:"Hemispheric",Frag:fragMeshHemiShader},{Name:"Edge",Frag:fragMeshEdgeShader},{Name:"Diffuse",Frag:fragMeshDiffuseEdgeShader},{Name:"Outline",Frag:fragMeshOutlineShader},{Name:"Toon",Frag:fragMeshToonShader},{Name:"Flat",Frag:fragFlatMeshShader},{Name:"Matcap",Frag:fragMeshMatcapShader}]);g0(this,"dragModes",{contrast:DRAG_MODE.contrast,measurement:DRAG_MODE.measurement,none:DRAG_MODE.none,pan:DRAG_MODE.pan,slicer3D:DRAG_MODE.slicer3D,callbackOnly:DRAG_MODE.callbackOnly});g0(this,"sliceTypeAxial",SLICE_TYPE.AXIAL);g0(this,"sliceTypeCoronal",SLICE_TYPE.CORONAL);g0(this,"sliceTypeSagittal",SLICE_TYPE.SAGITTAL);g0(this,"sliceTypeMultiplanar",SLICE_TYPE.MULTIPLANAR);g0(this,"sliceTypeRender",SLICE_TYPE.RENDER);g0(this,"onDragRelease",()=>{});g0(this,"onMouseUp",()=>{});g0(this,"onLocationChange",()=>{});g0(this,"onIntensityChange",()=>{});g0(this,"onImageLoaded",()=>{});g0(this,"onMeshLoaded",()=>{});g0(this,"onFrameChange",()=>{});g0(this,"onError",()=>{});g0(this,"onColormapChange",()=>{});g0(this,"onInfo",()=>{});g0(this,"onWarn",()=>{});g0(this,"onDebug",()=>{});g0(this,"onVolumeAddedFromUrl",()=>{});g0(this,"onVolumeWithUrlRemoved",()=>{});g0(this,"onVolumeUpdated",()=>{});g0(this,"onMeshAddedFromUrl",()=>{});g0(this,"onMeshAdded",()=>{});g0(this,"onMeshWithUrlRemoved",()=>{});g0(this,"onZoom3DChange",()=>{});g0(this,"onAzimuthElevationChange",()=>{});g0(this,"onClipPlaneChange",()=>{});g0(this,"onCustomMeshShaderAdded",()=>{});g0(this,"onMeshShaderChanged",()=>{});g0(this,"onMeshPropertyChanged",()=>{});g0(this,"onDocumentLoaded",()=>{});g0(this,"document",new NVDocument);g0(this,"mediaUrlMap",new Map);g0(this,"initialized",!1);g0(this,"currentDrawUndoBitmap");g0(this,"loadingText");for(const h in u)typeof u[h]=="function"?this[h]=u[h]:this.opts[h]=DEFAULT_OPTIONS[h]===void 0?DEFAULT_OPTIONS[h]:u[h];this.opts.isHighResolutionCapable?this.uiData.dpr=window.devicePixelRatio||1:this.uiData.dpr=1,this.currentDrawUndoBitmap=this.opts.maxDrawUndoBitmaps,this.opts.drawingEnabled&&this.createEmptyDrawing(),this.opts.thumbnail.length>0&&(this.thumbnailVisible=!0),this.loadingText=this.opts.loadingText,log.setLogLevel(this.opts.logLevel)}get scene(){return this.document.scene}get opts(){return this.document.opts}get sliceMosaicString(){return this.document.opts.sliceMosaicString||""}set sliceMosaicString(u){this.document.opts.sliceMosaicString=u}get volumes(){return this.document.volumes}set volumes(u){this.document.volumes=u}get meshes(){return this.document.meshes}set meshes(u){this.document.meshes=u}get drawBitmap(){return this.document.drawBitmap}set drawBitmap(u){this.document.drawBitmap=u}get volScaleMultiplier(){return this.scene.volScaleMultiplier}set volScaleMultiplier(u){this.setScale(u)}async saveScene(u="niivue.png"){function h(v,w){const C=document.createElement("a");document.body.appendChild(C),C.style.display="none";const k=window.URL.createObjectURL(v);C.href=k,C.download=w,C.click(),C.remove()}const g=this.canvas;if(!g)throw new Error("canvas not defined");this.drawScene(),g.toBlob(v=>{v&&(u===""&&(u=`niivue-screenshot-${new Date().toString()}.png`,u=u.replace(/\s/g,"_")),h(v,u))})}async attachTo(u,h=null){return await this.attachToCanvas(document.getElementById(u),h),log.debug("attached to element with id: ",u),this}async attachToCanvas(u,h=null){return this.canvas=u,h===null&&(h=navigator.hardwareConcurrency>6,log.debug("AntiAlias ",h," Threads ",navigator.hardwareConcurrency)),this.gl=this.canvas.getContext("webgl2",{alpha:!0,antialias:h}),log.info("NIIVUE VERSION ",version),this.canvas.parentElement.style.backgroundColor="black",this.opts.isResizeCanvas&&(this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.display="block",this.canvas.width=this.canvas.offsetWidth,this.canvas.height=this.canvas.offsetHeight,window.addEventListener("resize",this.resizeListener.bind(this)),this.resizeObserver=new ResizeObserver(this.resizeListener.bind(this)),this.resizeObserver.observe(this.canvas.parentElement)),this.registerInteractions(),await this.init(),this.drawScene(),this}syncWith(u,h={"2d":!0,"3d":!0}){this.otherNV=u,this.syncOpts=h}broadcastTo(u,h={"2d":!0,"3d":!0}){this.otherNV=u,this.syncOpts=h}sync(){if(!this.gl||!this.otherNV||typeof this.otherNV>"u"||!this.gl.canvas.matches(":focus"))return;const u=this.frac2mm(this.scene.crosshairPos);if(this.otherNV instanceof Niivue)this.syncOpts["2d"]&&(this.otherNV.scene.crosshairPos=this.otherNV.mm2frac(u)),this.syncOpts["3d"]&&(this.otherNV.scene.renderAzimuth=this.scene.renderAzimuth,this.otherNV.scene.renderElevation=this.scene.renderElevation),this.otherNV.drawScene(),this.otherNV.createOnLocationChange();else if(Array.isArray(this.otherNV))for(let h=0;h<this.otherNV.length;h++)this.otherNV[h]!==this&&(this.syncOpts["2d"]&&(this.otherNV[h].scene.crosshairPos=this.otherNV[h].mm2frac(u)),this.syncOpts["3d"]&&(this.otherNV[h].scene.renderAzimuth=this.scene.renderAzimuth,this.otherNV[h].scene.renderElevation=this.scene.renderElevation),this.otherNV[h].drawScene(),this.otherNV[h].createOnLocationChange())}arrayEquals(u,h){return Array.isArray(u)&&Array.isArray(h)&&u.length===h.length&&u.every((g,v)=>g===h[v])}resizeListener(){if(!(!this.canvas||!this.gl)){if(!this.opts.isResizeCanvas){this.opts.isHighResolutionCapable&&(log.warn("isHighResolutionCapable requires isResizeCanvas"),this.opts.isHighResolutionCapable=!1),this.uiData.dpr=1,this.drawScene();return}this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.display="block",this.opts.isHighResolutionCapable?(this.uiData.dpr=window.devicePixelRatio||1,log.debug("devicePixelRatio: "+this.uiData.dpr)):this.uiData.dpr=1,"width"in this.canvas.parentElement?(this.canvas.width=this.canvas.parentElement.width*this.uiData.dpr,this.canvas.height=this.canvas.parentElement.height*this.uiData.dpr):(this.canvas.width=this.canvas.offsetWidth*this.uiData.dpr,this.canvas.height=this.canvas.offsetHeight*this.uiData.dpr),this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height),this.drawScene()}}getRelativeMousePosition(u,h){if(h=h||u.target,!h)return;const g=h.getBoundingClientRect();return{x:u.clientX-g.left,y:u.clientY-g.top}}getNoPaddingNoBorderCanvasRelativeMousePosition(u,h){return h=h||u.target,this.getRelativeMousePosition(u,h)}mouseContextMenuListener(u){u.preventDefault()}mouseDownListener(u){u.preventDefault(),this.drawPenLocation=[NaN,NaN,NaN],this.drawPenAxCorSag=-1,this.uiData.mousedown=!0,log.debug("mouse down"),log.debug(u);const h=this.getNoPaddingNoBorderCanvasRelativeMousePosition(u,this.gl.canvas);if(!h)return;const[g,v]=[h.x*this.uiData.dpr,h.y*this.uiData.dpr],w=this.getLabelAtPoint([g,v]);if(w){for(const C of this.meshes)if(C.type===MeshType.CONNECTOME)for(const k of C.nodes)k.label===w&&(this.scene.crosshairPos=this.mm2frac([k.x,k.y,k.z]),this.updateGLVolume(),this.drawScene())}this.uiData.clickedTile=this.tileIndex(g,v),u.button===LEFT_MOUSE_BUTTON&&u.shiftKey?(this.uiData.mouseButtonCenterDown=!0,this.mouseCenterButtonHandler(u)):u.button===LEFT_MOUSE_BUTTON?(this.uiData.mouseButtonLeftDown=!0,this.mouseLeftButtonHandler(u)):u.button===RIGHT_MOUSE_BUTTON?(this.uiData.mouseButtonRightDown=!0,this.mouseRightButtonHandler(u)):u.button===CENTER_MOUSE_BUTTON&&(this.uiData.mouseButtonCenterDown=!0,this.mouseCenterButtonHandler(u))}mouseLeftButtonHandler(u){const h=this.getNoPaddingNoBorderCanvasRelativeMousePosition(u,this.gl.canvas);this.mouseDown(h.x,h.y),this.mouseClick(h.x,h.y)}mouseCenterButtonHandler(u){const h=this.getNoPaddingNoBorderCanvasRelativeMousePosition(u,this.gl.canvas);this.mousePos=[h.x*this.uiData.dpr,h.y*this.uiData.dpr],this.opts.dragMode!==DRAG_MODE.none&&(this.setDragStart(h.x,h.y),this.uiData.isDragging||(this.uiData.pan2DxyzmmAtMouseDown=clone(this.scene.pan2Dxyzmm)),this.uiData.isDragging=!0,this.uiData.dragClipPlaneStartDepthAziElev=this.scene.clipPlaneDepthAziElev)}mouseRightButtonHandler(u){const h=this.getNoPaddingNoBorderCanvasRelativeMousePosition(u,this.gl.canvas);this.mousePos=[h.x*this.uiData.dpr,h.y*this.uiData.dpr],this.opts.dragMode!==DRAG_MODE.none&&(this.setDragStart(h.x,h.y),this.uiData.isDragging||(this.uiData.pan2DxyzmmAtMouseDown=clone(this.scene.pan2Dxyzmm)),this.uiData.isDragging=!0,this.uiData.dragClipPlaneStartDepthAziElev=this.scene.clipPlaneDepthAziElev)}calculateMinMaxVoxIdx(u){if(u.length>2)throw new Error("array must not contain more than two values");return[Math.floor(Math.min(u[0],u[1])),Math.floor(Math.max(u[0],u[1]))]}calculateNewRange({volIdx:u=0}={}){if(this.opts.sliceType===SLICE_TYPE.RENDER&&this.sliceMosaicString.length<1||this.uiData.dragStart[0]===this.uiData.dragEnd[0]&&this.uiData.dragStart[1]===this.uiData.dragEnd[1])return;let h=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]);if(h[0]<0)return;const g=this.frac2vox(h,u);if(h=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]),h[0]<0)return;const v=this.frac2vox(h,u);let w=-Number.MAX_VALUE,C=Number.MAX_VALUE;const k=this.calculateMinMaxVoxIdx([g[0],v[0]]),U=this.calculateMinMaxVoxIdx([g[1],v[1]]),N=this.calculateMinMaxVoxIdx([g[2],v[2]]);g[0]-v[0]===0?k[1]=g[0]+1:g[1]-v[1]===0?U[1]=g[1]+1:g[2]-v[2]===0&&(N[1]=g[2]+1);const O=this.volumes[u].hdr,d=this.volumes[u].img;if(!O||!d)return;const M=O.dims[1],e=O.dims[2];for(let W=N[0];W<N[1];W++){const s0=W*M*e;for(let K=U[0];K<U[1];K++){const J=K*M;for(let D=k[0];D<k[1];D++){const Z=s0+J+D;C>d[Z]&&(C=d[Z]),w<d[Z]&&(w=d[Z])}}}if(C>=w)return;const b=intensityRaw2Scaled(O,C),z=intensityRaw2Scaled(O,w);this.volumes[u].cal_min=b,this.volumes[u].cal_max=z,this.onIntensityChange(this.volumes[u])}generateMouseUpCallback(u,h){const g=this.tileIndex(this.uiData.dragStart[0],this.uiData.dragStart[1]),v=this.tileIndex(this.uiData.dragEnd[0],this.uiData.dragEnd[1]);let w=-1;g===v&&(w=v);let C=-1;w>=0&&(C=this.screenSlices[w].axCorSag);const k=this.frac2mm(u),U=this.frac2mm(h),N=create$2();sub$1(N,fromValues$2(k[0],k[1],k[2]),fromValues$2(U[0],U[1],U[2]));const O=len(N),d=this.frac2vox(u),M=this.frac2vox(h);this.onDragRelease({fracStart:u,fracEnd:h,voxStart:d,voxEnd:M,mmStart:k,mmEnd:U,mmLength:O,tileIdx:w,axCorSag:C})}mouseUpListener(){function u(v){return Object.prototype.toString.call(v).indexOf("Function")>-1}const h={mouseButtonRightDown:this.uiData.mouseButtonRightDown,mouseButtonCenterDown:this.uiData.mouseButtonCenterDown,isDragging:this.uiData.isDragging,mousePos:this.mousePos,fracPos:this.canvasPos2frac(this.mousePos)};this.uiData.mousedown=!1,this.uiData.mouseButtonRightDown=!1;const g=this.uiData.mouseButtonCenterDown;if(this.uiData.mouseButtonCenterDown=!1,this.uiData.mouseButtonLeftDown=!1,this.drawPenFillPts.length>0?this.drawPenFilled():this.drawPenAxCorSag>=0&&this.drawAddUndoBitmap(),this.drawPenLocation=[NaN,NaN,NaN],this.drawPenAxCorSag=-1,u(this.onMouseUp)&&this.onMouseUp(h),this.uiData.isDragging){this.uiData.isDragging=!1,this.opts.dragMode===DRAG_MODE.callbackOnly&&this.drawScene();const v=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]),w=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);if(this.generateMouseUpCallback(v,w),this.opts.dragMode!==DRAG_MODE.contrast||g||this.uiData.dragStart[0]===this.uiData.dragEnd[0]&&this.uiData.dragStart[1]===this.uiData.dragEnd[1])return;this.calculateNewRange({volIdx:0}),this.refreshLayers(this.volumes[0],0)}this.drawScene()}checkMultitouch(u){if(this.uiData.touchdown&&!this.uiData.multiTouchGesture){const h=this.canvas.getBoundingClientRect();this.mouseDown(u.touches[0].clientX-h.left,u.touches[0].clientY-h.top),this.mouseClick(u.touches[0].clientX-h.left,u.touches[0].clientY-h.top)}}touchStartListener(u){u.preventDefault(),this.uiData.touchTimer||(this.uiData.touchTimer=setTimeout(()=>{this.resetBriCon(u)},this.opts.longTouchTimeout)),this.uiData.touchdown=!0,this.uiData.currentTouchTime=new Date().getTime();const h=this.uiData.currentTouchTime-this.uiData.lastTouchTime;if(h<this.opts.doubleTouchTimeout&&h>0){this.uiData.doubleTouch=!0,this.setDragStart(u.targetTouches[0].clientX-u.target.getBoundingClientRect().left,u.targetTouches[0].clientY-u.target.getBoundingClientRect().top),this.resetBriCon(u),this.uiData.lastTouchTime=this.uiData.currentTouchTime;return}else this.uiData.doubleTouch=!1,this.setDragStart(0,0),this.setDragEnd(0,0),this.uiData.lastTouchTime=this.uiData.currentTouchTime;this.uiData.touchdown&&u.touches.length<2?this.uiData.multiTouchGesture=!1:this.uiData.multiTouchGesture=!0,setTimeout(this.checkMultitouch.bind(this),1,u)}touchEndListener(u){if(u.preventDefault(),this.uiData.touchdown=!1,this.uiData.lastTwoTouchDistance=0,this.uiData.multiTouchGesture=!1,this.uiData.touchTimer&&(clearTimeout(this.uiData.touchTimer),this.uiData.touchTimer=null),this.uiData.isDragging){this.uiData.isDragging=!1,this.opts.dragMode===DRAG_MODE.contrast&&(this.calculateNewRange(),this.refreshLayers(this.volumes[0],0));const h=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]),g=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);this.generateMouseUpCallback(h,g)}this.mouseUpListener()}mouseMoveListener(u){if(this.uiData.mousedown){const h=this.getNoPaddingNoBorderCanvasRelativeMousePosition(u,this.gl.canvas);if(!h)return;const g=h.x*this.uiData.dpr,v=h.y*this.uiData.dpr;if(this.tileIndex(g,v)!==this.uiData.clickedTile)return;this.uiData.mouseButtonLeftDown?(this.mouseMove(h.x,h.y),this.mouseClick(h.x,h.y)):(this.uiData.mouseButtonRightDown||this.uiData.mouseButtonCenterDown)&&this.setDragEnd(h.x,h.y),this.drawScene(),this.uiData.prevX=this.uiData.currX,this.uiData.prevY=this.uiData.currY}}resetBriCon(u=null){if(this.uiData.isDragging)return;let h=!1;this.opts.sliceType===SLICE_TYPE.RENDER&&(h=!0);let g=0,v=0;if(u!==null&&("targetTouches"in u?(g=u.targetTouches[0].clientX-u.target.getBoundingClientRect().left,v=u.targetTouches[0].clientY-u.target.getBoundingClientRect().top):(g=u.offsetX,v=u.offsetY),g*=this.uiData.dpr,v*=this.uiData.dpr,this.inRenderTile(g,v)>=0&&(h=!0)),h){this.uiData.mouseDepthPicker=!0,this.drawScene(),this.drawScene();return}this.opts.dragMode!==DRAG_MODE.slicer3D&&(this.volumes.length<1||this.uiData.doubleTouch||(this.volumes[0].cal_min=this.volumes[0].robust_min,this.volumes[0].cal_max=this.volumes[0].robust_max,this.onIntensityChange(this.volumes[0]),this.refreshLayers(this.volumes[0],0),this.drawScene()))}setDragStart(u,h){u*=this.uiData.dpr,h*=this.uiData.dpr,this.uiData.dragStart[0]=u,this.uiData.dragStart[1]=h}setDragEnd(u,h){u*=this.uiData.dpr,h*=this.uiData.dpr,this.uiData.dragEnd[0]=u,this.uiData.dragEnd[1]=h}touchMoveListener(u){if(this.uiData.touchdown&&u.touches.length<2){const h=this.canvas.getBoundingClientRect();if(this.uiData.isDragging||(this.uiData.pan2DxyzmmAtMouseDown=clone(this.scene.pan2Dxyzmm)),this.uiData.isDragging=!0,this.uiData.doubleTouch&&this.uiData.isDragging){this.setDragEnd(u.targetTouches[0].clientX-u.target.getBoundingClientRect().left,u.targetTouches[0].clientY-u.target.getBoundingClientRect().top),this.drawScene();return}this.mouseClick(u.touches[0].clientX-h.left,u.touches[0].clientY-h.top),this.mouseMove(u.touches[0].clientX-h.left,u.touches[0].clientY-h.top)}else this.handlePinchZoom(u)}handlePinchZoom(u){if(u.targetTouches.length===2&&u.changedTouches.length===2){const h=Math.hypot(u.touches[0].pageX-u.touches[1].pageX,u.touches[0].pageY-u.touches[1].pageY),g=this.canvas.getBoundingClientRect();this.mousePos=[u.touches[0].clientX-g.left,u.touches[0].clientY-g.top],h<this.uiData.lastTwoTouchDistance?this.sliceScroll2D(-.01,u.touches[0].clientX-g.left,u.touches[0].clientY-g.top):this.sliceScroll2D(.01,u.touches[0].clientX-g.left,u.touches[0].clientY-g.top),this.uiData.lastTwoTouchDistance=h}}keyUpListener(u){if(u.code===this.opts.clipPlaneHotKey){const h=new Date().getTime();if(h-this.lastCalled>this.opts.keyDebounceTime){switch(this.currentClipPlaneIndex=(this.currentClipPlaneIndex+1)%7,this.currentClipPlaneIndex){case 0:this.scene.clipPlaneDepthAziElev=[2,0,0];break;case 1:this.scene.clipPlaneDepthAziElev=[0,270,0];break;case 2:this.scene.clipPlaneDepthAziElev=[0,90,0];break;case 3:this.scene.clipPlaneDepthAziElev=[0,0,0];break;case 4:this.scene.clipPlaneDepthAziElev=[0,180,0];break;case 5:this.scene.clipPlaneDepthAziElev=[0,0,-90];break;case 6:this.scene.clipPlaneDepthAziElev=[0,0,90];break}this.setClipPlane(this.scene.clipPlaneDepthAziElev)}this.lastCalled=h}else if(u.code===this.opts.viewModeHotKey){const h=new Date().getTime();h-this.lastCalled>this.opts.keyDebounceTime&&(this.setSliceType((this.opts.sliceType+1)%5),this.lastCalled=h)}}keyDownListener(u){u.code==="KeyH"&&this.opts.sliceType===SLICE_TYPE.RENDER?this.setRenderAzimuthElevation(this.scene.renderAzimuth-1,this.scene.renderElevation):u.code==="KeyL"&&this.opts.sliceType===SLICE_TYPE.RENDER?this.setRenderAzimuthElevation(this.scene.renderAzimuth+1,this.scene.renderElevation):u.code==="KeyJ"&&this.opts.sliceType===SLICE_TYPE.RENDER?this.setRenderAzimuthElevation(this.scene.renderAzimuth,this.scene.renderElevation+1):u.code==="KeyK"&&this.opts.sliceType===SLICE_TYPE.RENDER?this.setRenderAzimuthElevation(this.scene.renderAzimuth,this.scene.renderElevation-1):u.code==="KeyH"&&this.opts.sliceType!==SLICE_TYPE.RENDER?this.moveCrosshairInVox(-1,0,0):u.code==="KeyL"&&this.opts.sliceType!==SLICE_TYPE.RENDER?this.moveCrosshairInVox(1,0,0):u.code==="KeyU"&&this.opts.sliceType!==SLICE_TYPE.RENDER&&u.ctrlKey?this.moveCrosshairInVox(0,0,1):u.code==="KeyD"&&this.opts.sliceType!==SLICE_TYPE.RENDER&&u.ctrlKey?this.moveCrosshairInVox(0,0,-1):u.code==="KeyJ"&&this.opts.sliceType!==SLICE_TYPE.RENDER?this.moveCrosshairInVox(0,-1,0):u.code==="KeyK"&&this.opts.sliceType!==SLICE_TYPE.RENDER?this.moveCrosshairInVox(0,1,0):u.code==="KeyM"&&this.opts.sliceType!==SLICE_TYPE.RENDER?(this.opts.dragMode++,this.opts.dragMode>=DRAG_MODE.slicer3D&&(this.opts.dragMode=DRAG_MODE.none),log.info("drag mode changed to ",DRAG_MODE[this.opts.dragMode])):u.code==="ArrowLeft"?this.setFrame4D(this.volumes[0].id,this.volumes[0].frame4D-1):u.code==="ArrowRight"?this.setFrame4D(this.volumes[0].id,this.volumes[0].frame4D+1):u.code==="Slash"&&u.shiftKey&&alert(`NIIVUE VERSION: ${version}`)}wheelListener(u){if(u.preventDefault(),u.stopPropagation(),this.thumbnailVisible)return;const h=this.canvas.getBoundingClientRect();u.deltaY<0?this.sliceScroll2D(-.01,u.clientX-h.left,u.clientY-h.top):this.sliceScroll2D(.01,u.clientX-h.left,u.clientY-h.top)}registerInteractions(){if(!this.canvas)throw new Error("canvas undefined");this.canvas.addEventListener("mousedown",this.mouseDownListener.bind(this)),this.canvas.addEventListener("mouseup",this.mouseUpListener.bind(this)),this.canvas.addEventListener("mousemove",this.mouseMoveListener.bind(this)),this.canvas.addEventListener("touchstart",this.touchStartListener.bind(this)),this.canvas.addEventListener("touchend",this.touchEndListener.bind(this)),this.canvas.addEventListener("touchmove",this.touchMoveListener.bind(this)),this.canvas.addEventListener("wheel",this.wheelListener.bind(this)),this.canvas.addEventListener("contextmenu",this.mouseContextMenuListener.bind(this)),this.canvas.addEventListener("dblclick",this.resetBriCon.bind(this)),this.canvas.addEventListener("dragenter",this.dragEnterListener.bind(this),!1),this.canvas.addEventListener("dragover",this.dragOverListener.bind(this),!1),this.canvas.addEventListener("drop",this.dropListener.bind(this),!1),this.canvas.setAttribute("tabindex","0"),this.canvas.addEventListener("keyup",this.keyUpListener.bind(this),!1),this.canvas.addEventListener("keydown",this.keyDownListener.bind(this),!1)}dragEnterListener(u){u.stopPropagation(),u.preventDefault()}dragOverListener(u){u.stopPropagation(),u.preventDefault()}getFileExt(u,h=!0){log.debug("fullname: ",u);const g=/(?:\.([^.]+))?$/;let v=g.exec(u)[1];return v=v.toUpperCase(),v==="GZ"&&(v=g.exec(u.slice(0,-3))[1],v=v.toUpperCase()),h?v:v.toLowerCase()}async addVolumeFromUrl(u){const h=await NVImage.loadFromUrl(u);return this.document.addImageOptions(h,u),h.onColormapChange=this.onColormapChange,this.mediaUrlMap.set(h,u.url),this.onVolumeAddedFromUrl&&this.onVolumeAddedFromUrl(u,h),this.addVolume(h),h}getMediaByUrl(u){return[...this.mediaUrlMap.entries()].filter(h=>h[1]===u).map(h=>h[0]).pop()}removeVolumeByUrl(u){const h=this.getMediaByUrl(u);if(h)this.removeVolume(h);else throw new Error("No volume with URL present")}readDirectory(u){const h=u.createReader();let g=[];const v=async C=>{const k=[],U=async N=>new Promise((O,d)=>N.file(O,d));for(let N=0;N<C.length;N++)k.push(await U(C[N]));return k},w=()=>{h.readEntries(C=>{C.length?(g=g.concat(C),w()):v(g).then(k=>{NVImage.loadFromFile({file:k,name:u.name,urlImgData:null,imageType:NVIMAGE_TYPE.DCM_FOLDER}).then(U=>this.addVolume(U)).catch(U=>{throw U})}).catch(k=>{throw k})})};return w(),g}isMeshExt(u){const h=this.getFileExt(u);return log.debug("dropped ext"),log.debug(h),MESH_EXTENSIONS.includes(h)}async loadFromArrayBuffer(u,h){const g=this.getFileExt(h);if(MESH_EXTENSIONS.includes(g)){await this.addMeshFromUrl({url:h,buffer:u});return}const v=NVImageFromUrlOptions(h);v.buffer=u,v.name=h,await this.addVolumeFromUrl(v)}async loadFromFile(u){const h=this.getFileExt(u.name);if(MESH_EXTENSIONS.includes(h)){await NVMesh.loadFromFile({file:u,gl:this.gl,name:u.name}).then(g=>{this.addMesh(g)});return}await NVImage.loadFromFile({file:u,name:u.name}).then(g=>{this.addVolume(g)})}dropListener(u){if(u.stopPropagation(),u.preventDefault(),!this.opts.dragAndDropEnabled)return;const h=u.dataTransfer;if(!h)return;const g=h.getData("text/uri-list");if(g){const v=NVImageFromUrlOptions(g),w=this.getFileExt(g);log.debug("dropped ext"),log.debug(w),MESH_EXTENSIONS.includes(w)?this.addMeshFromUrl({url:g}).catch(C=>{throw C}):w==="NVD"?this.loadDocumentFromUrl(g).catch(C=>{throw C}):this.addVolumeFromUrl(v).catch(C=>{throw C})}else{const v=h.items;if(v.length>0){!u.shiftKey&&!u.altKey&&(this.volumes=[],this.overlays=[],this.meshes=[]),this.closeDrawing();for(const w of Array.from(v)){const C=w.webkitGetAsEntry();if(log.debug(C),!C)throw new Error("could not get entry from file");if(C.isFile){const k=this.getFileExt(C.name);if(k==="PNG"){C.file(N=>{this.loadBmpTexture(N).catch(O=>{throw O})});continue}let U;if(C.name.lastIndexOf("HEAD")!==-1)for(const N of Array.from(v)){const O=N.webkitGetAsEntry();if(!O)throw new Error("could not get paired entry");const d=C.name.substring(0,C.name.lastIndexOf("HEAD")),M=O.name.substring(0,O.name.lastIndexOf("BRIK"));d===M&&(U=O)}if(C.name.lastIndexOf("BRIK")!==-1)continue;if(MESH_EXTENSIONS.includes(k)){C.file(N=>{NVMesh.loadFromFile({file:N,gl:this.gl,name:N.name}).then(O=>{this.addMesh(O)}).catch(O=>{throw O})});continue}else if(k==="NVD"){C.file(N=>{NVDocument.loadFromFile(N).then(O=>{this.loadDocument(O),log.debug("loaded document")}).catch(O=>{throw O})});break}C.file(N=>{U?U.file(O=>{NVImage.loadFromFile({file:N,urlImgData:O,limitFrames4D:this.opts.limitFrames4D}).then(d=>{this.addVolume(d)}).catch(d=>{throw d})}):NVImage.loadFromFile({file:N,urlImgData:U,limitFrames4D:this.opts.limitFrames4D}).then(O=>{u.altKey?(log.debug("alt key detected: assuming this is a drawing overlay"),this.drawClearAllUndoBitmaps(),this.loadDrawing(O)):this.addVolume(O)}).catch(O=>{throw O})})}else C.isDirectory&&this.readDirectory(C)}}}this.drawScene()}setMultiplanarPadPixels(u){this.opts.multiplanarPadPixels=u,this.drawScene()}setMultiplanarLayout(u){typeof u=="string"&&(u=parseInt(u)),this.opts.multiplanarLayout=u,this.drawScene()}setCornerOrientationText(u){this.opts.isCornerOrientationText=u,this.updateGLVolume()}setRadiologicalConvention(u){this.opts.isRadiologicalConvention=u,this.updateGLVolume()}setDefaults(u={},h=!1){this.document.opts={...DEFAULT_OPTIONS},this.scene.sceneData={...INITIAL_SCENE_DATA};for(const g in u)typeof u[g]=="function"?this[g]=u[g]:this.opts[g]=DEFAULT_OPTIONS[g]===void 0?DEFAULT_OPTIONS[g]:u[g];if(this.scene.pan2Dxyzmm=[0,0,0,1],h&&this.volumes&&this.volumes.length>0)for(let g=0;g<this.volumes.length;g++)this.volumes[g].cal_min=this.volumes[g].robust_min,this.volumes[g].cal_max=this.volumes[g].robust_max;this.updateGLVolume()}setMeshThicknessOn2D(u){this.opts.meshThicknessOn2D=u,this.updateGLVolume()}setSliceMosaicString(u){this.sliceMosaicString=u,this.updateGLVolume()}setSliceMM(u){this.opts.isSliceMM=u,this.updateGLVolume()}setAdditiveBlend(u){this.opts.isAdditiveBlend=u,this.updateGLVolume()}getRadiologicalConvention(){return this.opts.isRadiologicalConvention}setHighResolutionCapable(u){this.opts.isHighResolutionCapable=u,u&&!this.opts.isResizeCanvas&&(log.warn("isHighResolutionCapable requires isResizeCanvas"),this.opts.isHighResolutionCapable=!1),this.opts.isHighResolutionCapable||(this.uiData.dpr=1),this.resizeListener(),this.drawScene()}addVolume(u){this.volumes.push(u);const h=this.volumes.length===1?0:this.volumes.length-1;this.setVolume(u,h),this.onImageLoaded(u),log.debug("loaded volume",u.name),log.debug(u)}addMesh(u){this.meshes.push(u);const h=this.meshes.length===1?0:this.meshes.length-1;this.setMesh(u,h),this.onMeshLoaded(u)}getVolumeIndexByID(u){const h=this.volumes.length;for(let g=0;g<h;g++)if(this.volumes[g].id===u)return g;return-1}drawAddUndoBitmap(){if(!this.drawBitmap||this.drawBitmap.length<1){log.debug("drawAddUndoBitmap error: No drawing open");return}this.currentDrawUndoBitmap++,this.currentDrawUndoBitmap>=this.opts.maxDrawUndoBitmaps&&(this.currentDrawUndoBitmap=0),this.drawUndoBitmaps[this.currentDrawUndoBitmap]=encodeRLE(this.drawBitmap)}drawClearAllUndoBitmaps(){if(this.currentDrawUndoBitmap=this.opts.maxDrawUndoBitmaps,!(!this.drawUndoBitmaps||this.drawUndoBitmaps.length<1))for(let u=this.drawUndoBitmaps.length-1;u>=0;u--)this.drawUndoBitmaps[u]=new Uint8Array}drawUndo(){if(this.drawUndoBitmaps.length<1){log.debug("undo bitmaps not loaded");return}if(this.currentDrawUndoBitmap--,this.currentDrawUndoBitmap<0&&(this.currentDrawUndoBitmap=this.drawUndoBitmaps.length-1),this.currentDrawUndoBitmap>=this.drawUndoBitmaps.length&&(this.currentDrawUndoBitmap=0),this.drawUndoBitmaps[this.currentDrawUndoBitmap].length<2){log.debug("drawUndo is misbehaving");return}this.drawBitmap=decodeRLE(this.drawUndoBitmaps[this.currentDrawUndoBitmap],this.drawBitmap.length),this.refreshDrawing(!0)}loadDrawing(u){if(this.drawBitmap&&log.debug("Overwriting open drawing!"),!this.back)throw new Error("back undefined");this.drawClearAllUndoBitmaps();const h=u.hdr.dims;if(h[1]!==this.back.hdr.dims[1]||h[2]!==this.back.hdr.dims[2]||h[3]!==this.back.hdr.dims[3])return log.debug("drawing dimensions do not match background image"),!1;u.img.constructor!==Uint8Array&&log.debug("Drawings should be UINT8");const g=u.permRAS,v=h[1]*h[2]*h[3];this.drawBitmap=new Uint8Array(v),this.drawTexture=this.r8Tex(this.drawTexture,TEXTURE7_DRAW,this.back.dims,!0);const w=[0,0,0];for(let z=0;z<3;z++)for(let W=0;W<3;W++)Math.abs(g[z])-1===W&&(w[W]=z*Math.sign(g[z]));let C=1;const k=[1,1,1],U=[!1,!1,!1];for(let z=0;z<w.length;z++)for(let W=0;W<w.length;W++)Math.abs(w[W])===z&&(k[W]=C,(w[W]<0||Object.is(w[W],-0))&&(U[W]=!0),C*=h[W+1]);let N=NVUtilities.range(0,h[1]-1,1);U[0]&&(N=NVUtilities.range(h[1]-1,0,-1));for(let z=0;z<h[1];z++)N[z]*=k[0];let O=NVUtilities.range(0,h[2]-1,1);U[1]&&(O=NVUtilities.range(h[2]-1,0,-1));for(let z=0;z<h[2];z++)O[z]*=k[1];let d=NVUtilities.range(0,h[3]-1,1);U[2]&&(d=NVUtilities.range(h[3]-1,0,-1));for(let z=0;z<h[3];z++)d[z]*=k[2];const M=u.img,e=this.drawBitmap;let b=0;for(let z=0;z<h[3];z++)for(let W=0;W<h[2];W++)for(let s0=0;s0<h[1];s0++)e[N[s0]+O[W]+d[z]]=M[b],b++;return this.drawAddUndoBitmap(),this.refreshDrawing(!1),this.drawScene(),!0}binarize(u){const h=u.hdr.dims,g=h[1]*h[2]*h[3],v=new Uint8Array(g);for(let w=0;w<g;w++)u.img[w]!==0&&(v[w]=1);u.img=v,u.hdr.datatypeCode=NiiDataType.DT_UINT8,u.hdr.cal_min=0,u.hdr.cal_max=1}async loadDrawingFromUrl(u,h=!1){this.drawBitmap&&log.debug("Overwriting open drawing!"),this.drawClearAllUndoBitmaps();let g=!1;try{const v=await NVImage.loadFromUrl(NVImageFromUrlOptions(u));h&&await this.binarize(v),g=this.loadDrawing(v)}catch{log.error("loadDrawingFromUrl() failed to load "+u),this.drawClearAllUndoBitmaps()}return g}findOtsu(u=2){if(this.volumes.length<1)return[];const h=this.volumes[0].img,g=h.length;if(g<1)return[];const v=256,w=v-1,C=new Array(v).fill(0),k=this.volumes[0].cal_min,U=this.volumes[0].cal_max;if(U<=k)return[];const N=(U-k)/v;function O(K){return K*N+k}const d=(v-1)/Math.abs(U-k),M=this.volumes[0].hdr.scl_inter,e=this.volumes[0].hdr.scl_slope;for(let K=0;K<g;K++){let J=h[K]*e+M;J=Math.min(Math.max(J,k),U),J=Math.round((J-k)*d),C[J]++}const b=Array(v).fill(0).map(()=>Array(v).fill(0)),z=Array(v).fill(0).map(()=>Array(v).fill(0));for(let K=1;K<v;++K)b[K][K]=C[K],z[K][K]=K*C[K];for(let K=1;K<v-1;++K)b[1][K+1]=b[1][K]+C[K+1],z[1][K+1]=z[1][K]+(K+1)*C[K+1];for(let K=2;K<v;K++)for(let J=K+1;J<v;J++)b[K][J]=b[1][J]-b[1][K-1],z[K][J]=z[1][J]-z[1][K-1];for(let K=1;K<v;++K)for(let J=K+1;J<v;J++)b[K][J]!==0&&(b[K][J]=z[K][J]*z[K][J]/b[K][J]);let W=0;const s0=[1/0,1/0,1/0];if(u>3)for(let K=0;K<v-3;K++)for(let J=K+1;J<v-2;J++)for(let D=J+1;D<v-1;D++){const Z=b[0][K]+b[K+1][J]+b[J+1][D]+b[D+1][w];Z>W&&(s0[0]=K,s0[1]=J,s0[2]=D,W=Z)}else if(u===3)for(let K=0;K<v-2;K++)for(let J=K+1;J<v-1;J++){const D=b[0][K]+b[K+1][J]+b[J+1][w];D>W&&(s0[0]=K,s0[1]=J,W=D)}else for(let K=0;K<v-1;K++){const J=b[0][K]+b[K+1][w];J>W&&(s0[0]=K,W=J)}return[O(s0[0]),O(s0[1]),O(s0[2])]}drawOtsu(u=2){if(this.volumes.length===0)return;const h=this.volumes[0].img.length,g=this.findOtsu(u);if(g.length<3)return;this.drawBitmap||this.createEmptyDrawing();const v=this.drawBitmap,w=this.volumes[0].img;for(let C=0;C<h;C++){if(v[C]!==0)continue;const k=w[C];k>g[0]&&(v[C]=1),k>g[1]&&(v[C]=2),k>g[2]&&(v[C]=3)}this.drawAddUndoBitmap(),this.refreshDrawing(!0)}removeHaze(u=5,h=0){const g=this.volumes[h].img,v=this.volumes[h].hdr,w=g.length;let C=2;(u===5||u===1)&&(C=4),(u===4||u===2)&&(C=3);const k=this.findOtsu(C);if(k.length<3)return;let U=k[0];u===1&&(U=k[2]),u===2&&(U=k[1]);const N=v.scl_inter,O=v.scl_slope,d=this.volumes[h].global_min;for(let M=0;M<w;M++)g[M]*O+N<U&&(g[M]=d);this.refreshLayers(this.volumes[h],0),this.drawScene()}saveImage(u=defaultSaveImageOptions){var k;const h={...defaultSaveImageOptions,...u},{filename:g,isSaveDrawing:v,volumeByIndex:w}=h;if(log.debug("saveImage",g,v,w),((k=this.back)==null?void 0:k.dims)===void 0)return log.debug("No voxelwise image open"),!1;if(v){if(!this.drawBitmap)return log.debug("No drawing open"),!1;const U=this.volumes[0].permRAS;if(U[0]===1&&U[1]===2&&U[2]===3)return log.debug("saving drawing"),this.volumes[0].saveToDisk(g,this.drawBitmap);{log.debug("saving drawing");const N=this.volumes[0].hdr.dims,O=[0,0,0];for(let Z=0;Z<3;Z++)for(let X=0;X<3;X++)Math.abs(U[Z])-1===X&&(O[X]=Z*Math.sign(U[Z]));let d=1;const M=[1,1,1],e=[!1,!1,!1];for(let Z=0;Z<O.length;Z++)for(let X=0;X<O.length;X++)Math.abs(O[X])===Z&&(M[X]=d,(O[X]<0||Object.is(O[X],-0))&&(e[X]=!0),d*=N[X+1]);let b=NVUtilities.range(0,N[1]-1,1);e[0]&&(b=NVUtilities.range(N[1]-1,0,-1));for(let Z=0;Z<N[1];Z++)b[Z]*=M[0];let z=NVUtilities.range(0,N[2]-1,1);e[1]&&(z=NVUtilities.range(N[2]-1,0,-1));for(let Z=0;Z<N[2];Z++)z[Z]*=M[1];let W=NVUtilities.range(0,N[3]-1,1);e[2]&&(W=NVUtilities.range(N[3]-1,0,-1));for(let Z=0;Z<N[3];Z++)W[Z]*=M[2];const s0=new Uint8Array(this.drawBitmap),K=new Uint8Array(N[1]*N[2]*N[3]);let J=0;for(let Z=0;Z<N[3];Z++)for(let X=0;X<N[2];X++)for(let r0=0;r0<N[1];r0++)K[J]=s0[b[r0]+z[X]+W[Z]],J++;return log.debug("saving drawing"),this.volumes[0].saveToDisk(g,K)}}return log.debug("saving image"),this.volumes[w].saveToDisk(g)}getMeshIndexByID(u){if(typeof u=="number")return u>=this.meshes.length?-1:u;const h=this.meshes.length;for(let g=0;g<h;g++)if(this.meshes[g].id===u)return g;return-1}setMeshProperty(u,h,g){const v=this.getMeshIndexByID(u);if(v<0){log.warn("setMeshProperty() id not loaded",u);return}this.meshes[v].setProperty(h,g,this.gl),this.updateGLVolume(),this.onMeshPropertyChanged(v,h,g)}indexNearestXYZmm(u,h,g,v){const w=this.getMeshIndexByID(u);return w<0?(log.warn("indexNearestXYZmm() id not loaded",u),[NaN,NaN]):this.meshes[w].indexNearestXYZmm(h,g,v)}reverseFaces(u){const h=this.getMeshIndexByID(u);if(h<0){log.warn("reverseFaces() id not loaded",u);return}this.meshes[h].reverseFaces(this.gl),this.updateGLVolume()}setMeshLayerProperty(u,h,g,v){const w=this.getMeshIndexByID(u);if(w<0){log.warn("setMeshLayerProperty() id not loaded",u);return}this.meshes[w].setLayerProperty(h,g,v,this.gl),this.updateGLVolume()}setPan2Dxyzmm(u){this.scene.pan2Dxyzmm=u,this.opts.yoke3Dto2DZoom&&(this.scene.volScaleMultiplier=u[3]),this.drawScene()}setRenderAzimuthElevation(u,h){this.scene.renderAzimuth=u,this.scene.renderElevation=h,this.onAzimuthElevationChange(u,h),this.drawScene()}getOverlayIndexByID(u){const h=this.overlays.length;for(let g=0;g<h;g++)if(this.overlays[g].id===u)return g;return-1}setVolume(u,h=0){const g=this.volumes.length;if(h>g)return;const v=this.getVolumeIndexByID(u.id);h===0?(this.volumes.splice(v,1),this.volumes.unshift(u),this.back=this.volumes[0],this.overlays=this.volumes.slice(1)):h<0?(this.volumes.splice(this.getVolumeIndexByID(u.id),1),this.back=this.volumes[0],this.volumes.length>1?this.overlays=this.volumes.slice(1):this.overlays=[]):(this.volumes.splice(v,1),this.volumes.splice(h,0,u),this.overlays=this.volumes.slice(1),this.back=this.volumes[0]),this.updateGLVolume()}setMesh(u,h=0){this.meshes.forEach(w=>{log.debug("MESH: ",w.name)});const g=this.meshes.length;if(h>g)return;const v=this.getMeshIndexByID(u.id);h===0?(this.meshes.splice(v,1),this.meshes.unshift(u)):h<0?this.meshes.splice(this.getMeshIndexByID(u.id),1):(this.meshes.splice(v,1),this.meshes.splice(h,0,u)),this.updateGLVolume(),this.meshes.forEach(w=>{log.debug(w.name)})}removeVolume(u){if(this.setVolume(u,-1),this.mediaUrlMap.has(u)){const h=this.mediaUrlMap.get(u);this.onVolumeWithUrlRemoved(h),this.mediaUrlMap.delete(u)}this.drawScene()}removeVolumeByIndex(u){if(u>=this.volumes.length)throw new Error("Index of volume out of bounds");this.removeVolume(this.volumes[u])}removeMesh(u){if(this.setMesh(u,-1),this.mediaUrlMap.has(u)){const h=this.mediaUrlMap.get(u);this.onMeshWithUrlRemoved(h),this.mediaUrlMap.delete(u)}}removeMeshByUrl(u){const h=this.getMediaByUrl(u);h&&(this.removeMesh(h),this.mediaUrlMap.delete(h),this.onMeshWithUrlRemoved(u))}moveVolumeToBottom(u){this.setVolume(u,0)}moveVolumeUp(u){const h=this.getVolumeIndexByID(u.id);this.setVolume(u,h+1)}moveVolumeDown(u){const h=this.getVolumeIndexByID(u.id);this.setVolume(u,h-1)}moveVolumeToTop(u){this.setVolume(u,this.volumes.length-1)}mouseDown(u,h){u*=this.uiData.dpr,h*=this.uiData.dpr,this.mousePos=[u,h]}mouseMove(u,h){u*=this.uiData.dpr,h*=this.uiData.dpr;const g=(u-this.mousePos[0])/this.uiData.dpr,v=(h-this.mousePos[1])/this.uiData.dpr;this.mousePos=[u,h],!(this.inRenderTile(u,h)<0)&&(Math.abs(g)<1&&Math.abs(v)<1||(this.scene.renderAzimuth+=g,this.scene.renderElevation+=v,this.drawScene()))}sph2cartDeg(u,h){const g=-h*(Math.PI/180),v=(u-90)%360*(Math.PI/180),w=[Math.cos(g)*Math.cos(v),Math.cos(g)*Math.sin(v),Math.sin(g)],C=Math.sqrt(w[0]*w[0]+w[1]*w[1]+w[2]*w[2]);return C<=0||(w[0]/=C,w[1]/=C,w[2]/=C),w}setClipPlane(u){const h=this.sph2cartDeg(u[1]+180,u[2]);this.scene.clipPlane=[h[0],h[1],h[2],u[0]],this.scene.clipPlaneDepthAziElev=u,this.onClipPlaneChange(this.scene.clipPlane),this.drawScene()}setCrosshairColor(u){this.opts.crosshairColor=u,this.drawScene()}setCrosshairWidth(u){this.opts.crosshairWidth=u,this.crosshairs3D&&(this.crosshairs3D.mm[0]=NaN),this.drawScene()}setDrawColormap(u){this.drawLut=cmapper.makeDrawLut(u),this.updateGLVolume()}setDrawingEnabled(u){this.opts.drawingEnabled=u,this.opts.drawingEnabled&&(this.drawBitmap||this.createEmptyDrawing()),this.drawScene()}setPenValue(u,h=!1){this.opts.penValue=u,this.opts.isFilledPen=h,this.drawScene()}setDrawOpacity(u){this.drawOpacity=u,this.drawScene()}setSelectionBoxColor(u){this.opts.selectionBoxColor=u}sliceScroll2D(u,h,g,v=!0){if(this.inGraphTile(h,g)){let w=this.volumes[0].frame4D;u>0&&w++,u<0&&w--,this.setFrame4D(this.volumes[0].id,w);return}if(u!==0&&this.opts.dragMode===DRAG_MODE.pan&&this.inRenderTile(this.uiData.dpr*h,this.uiData.dpr*g)===-1){let w=this.scene.pan2Dxyzmm[3]*(1+10*u);w=Math.round(w*10)/10;const C=this.scene.pan2Dxyzmm[3]-w;this.opts.yoke3Dto2DZoom&&(this.scene.volScaleMultiplier=w),this.scene.pan2Dxyzmm[3]=w;const k=this.frac2mm(this.scene.crosshairPos);this.scene.pan2Dxyzmm[0]+=C*k[0],this.scene.pan2Dxyzmm[1]+=C*k[1],this.scene.pan2Dxyzmm[2]+=C*k[2],this.drawScene();return}this.mouseClick(h,g,u,v)}setSliceType(u){return this.opts.sliceType=u,this.drawScene(),this}setOpacity(u,h){if(this.volumes[u].opacity=h,u===0){this.drawScene();return}this.updateGLVolume()}setScale(u){this.scene.volScaleMultiplier=u,this.drawScene()}setClipPlaneColor(u){this.opts.clipPlaneColor=u,this.renderShader.use(this.gl),this.gl.uniform4fv(this.renderShader.uniforms.clipPlaneColor,this.opts.clipPlaneColor),this.drawScene()}async setVolumeRenderIllumination(u=0){this.renderShader=this.renderVolumeShader,u>0&&(this.renderShader=this.renderGradientShader),u<0&&(this.renderShader=this.renderSliceShader),this.initRenderShader(this.renderShader,u),this.renderShader.use(this.gl),this.setClipPlaneColor(this.opts.clipPlaneColor),this.gradientTextureAmount=u,this.refreshLayers(this.volumes[0],0),this.drawScene()}overlayRGBA(u){const h=u.hdr,g=h.dims[1]*h.dims[2]*h.dims[3],v=new Uint8ClampedArray(g*4),w=.2*Math.min(Math.min(h.dims[1],h.dims[2]),h.dims[3]),C=.5*h.dims[1],k=.5*h.dims[2],U=.5*h.dims[3];let N=0;for(let O=0;O<h.dims[3];O++)for(let d=0;d<h.dims[2];d++)for(let M=0;M<h.dims[1];M++){const e=Math.abs(M-C),b=Math.abs(d-k),z=Math.abs(O-U),W=Math.sqrt(e*e+b*b+z*z);let s0=0;W<w&&(s0=255),v[N++]=0,v[N++]=s0,v[N++]=0,v[N++]=s0*.5}return v}vox2mm(u,h){return NVUtilities.vox2mm(u,h)}cloneVolume(u){return this.volumes[u].clone()}async loadDocumentFromUrl(u){const h=await NVDocument.loadFromUrl(u);this.loadDocument(h)}loadDocument(u){this.volumes=[],this.meshes=[],this.document=u,this.document.labels=this.document.labels?this.document.labels:[];const h={...DEFAULT_OPTIONS,...u.opts};this.scene.pan2Dxyzmm=u.scene.pan2Dxyzmm?u.scene.pan2Dxyzmm:[0,0,0,1],this.document.opts=h,this.setClipPlane(this.scene.clipPlaneDepthAziElev),log.debug("load document",u),this.mediaUrlMap.clear(),this.createEmptyDrawing();const g=u.encodedImageBlobs;for(let w=0;w<u.imageOptionsArray.length;w++){const C=u.imageOptionsArray[w],k=g[w];if(k){"colorMap"in C&&(C.colormap=C.colorMap);const U=NVImage.loadFromBase64({base64:k,...C});if(U){if(U.colormapLabel){const N=Object.keys(U.colormapLabel.lut).length,O=new Uint8ClampedArray(N);for(const d in U.colormapLabel.lut)O[d]=U.colormapLabel.lut[d];U.colormapLabel.lut=O}this.addVolume(U)}}}this.volumes.length>0&&(this.back=this.volumes[0]);const v=u.encodedDrawingBlob;if(v){const w=u.imageOptionsArray[0],C=NVImage.loadFromBase64({base64:v,...w});C&&this.loadDrawing(C)}for(const w of u.meshDataObjects??[]){const C={gl:this.gl,...w};log.debug(C);const k=new NVMesh(C.pts,C.tris,C.name,C.rgba255,C.opacity,C.visible,this.gl,C.connectome,C.dpg,C.dps,C.dpv);k.meshShaderIndex=C.meshShaderIndex,k.layers=C.layers,k.updateMesh(this.gl),log.debug(k),this.addMesh(k)}if(u.data.connectomes)for(const w of u.data.connectomes){const C=JSON.parse(w),k=this.loadConnectomeAsMesh(C);k.updateMesh(this.gl),this.addMesh(k)}return this.updateGLVolume(),this.drawScene(),this.onDocumentLoaded(u),this}generateLoadDocumentJavaScript(u,h){const g=this.json(),v=NVUtilities.compressToBase64String(JSON.stringify(g));return`
1617
1617
  ${h}
1618
1618
 
1619
1619
  function saveNiivueAsHtml(pageName) {