diff --git "a/assets/index-Cno3rxPp.js" "b/assets/index-Cno3rxPp.js" new file mode 100644--- /dev/null +++ "b/assets/index-Cno3rxPp.js" @@ -0,0 +1,2340 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/blosc-CrUiACa7.js","assets/chunk-INHXZS53-D3tQiqtZ.js","assets/lz4-B_Exjfmr.js","assets/zstd-u5eweWyS.js"])))=>i.map(i=>d[i]); +(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))s(r);new MutationObserver(r=>{for(const c of r)if(c.type==="childList")for(const l of c.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&s(l)}).observe(document,{childList:!0,subtree:!0});function n(r){const c={};return r.integrity&&(c.integrity=r.integrity),r.referrerPolicy&&(c.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?c.credentials="include":r.crossOrigin==="anonymous"?c.credentials="omit":c.credentials="same-origin",c}function s(r){if(r.ep)return;r.ep=!0;const c=n(r);fetch(r.href,c)}})();function RA(i){return i&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i}var Ah={exports:{}},za={};var wd;function NA(){if(wd)return za;wd=1;var i=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function n(s,r,c){var l=null;if(c!==void 0&&(l=""+c),r.key!==void 0&&(l=""+r.key),"key"in r){c={};for(var d in r)d!=="key"&&(c[d]=r[d])}else c=r;return r=c.ref,{$$typeof:i,type:s,key:l,ref:r!==void 0?r:null,props:c}}return za.Fragment=t,za.jsx=n,za.jsxs=n,za}var bd;function VA(){return bd||(bd=1,Ah.exports=NA()),Ah.exports}var ht=VA(),ph={exports:{}},wt={};var Cd;function LA(){if(Cd)return wt;Cd=1;var i=Symbol.for("react.transitional.element"),t=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),s=Symbol.for("react.strict_mode"),r=Symbol.for("react.profiler"),c=Symbol.for("react.consumer"),l=Symbol.for("react.context"),d=Symbol.for("react.forward_ref"),h=Symbol.for("react.suspense"),u=Symbol.for("react.memo"),m=Symbol.for("react.lazy"),g=Symbol.for("react.activity"),A=Symbol.iterator;function v(G){return G===null||typeof G!="object"?null:(G=A&&G[A]||G["@@iterator"],typeof G=="function"?G:null)}var y={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},w=Object.assign,b={};function C(G,j,$){this.props=G,this.context=j,this.refs=b,this.updater=$||y}C.prototype.isReactComponent={},C.prototype.setState=function(G,j){if(typeof G!="object"&&typeof G!="function"&&G!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,G,j,"setState")},C.prototype.forceUpdate=function(G){this.updater.enqueueForceUpdate(this,G,"forceUpdate")};function S(){}S.prototype=C.prototype;function E(G,j,$){this.props=G,this.context=j,this.refs=b,this.updater=$||y}var M=E.prototype=new S;M.constructor=E,w(M,C.prototype),M.isPureReactComponent=!0;var N=Array.isArray;function U(){}var T={H:null,A:null,T:null,S:null},F=Object.prototype.hasOwnProperty;function I(G,j,$){var et=$.ref;return{$$typeof:i,type:G,key:j,ref:et!==void 0?et:null,props:$}}function B(G,j){return I(G.type,j,G.props)}function V(G){return typeof G=="object"&&G!==null&&G.$$typeof===i}function R(G){var j={"=":"=0",":":"=2"};return"$"+G.replace(/[=:]/g,function($){return j[$]})}var Y=/\/+/g;function P(G,j){return typeof G=="object"&&G!==null&&G.key!=null?R(""+G.key):j.toString(36)}function X(G){switch(G.status){case"fulfilled":return G.value;case"rejected":throw G.reason;default:switch(typeof G.status=="string"?G.then(U,U):(G.status="pending",G.then(function(j){G.status==="pending"&&(G.status="fulfilled",G.value=j)},function(j){G.status==="pending"&&(G.status="rejected",G.reason=j)})),G.status){case"fulfilled":return G.value;case"rejected":throw G.reason}}throw G}function L(G,j,$,et,ot){var mt=typeof G;(mt==="undefined"||mt==="boolean")&&(G=null);var vt=!1;if(G===null)vt=!0;else switch(mt){case"bigint":case"string":case"number":vt=!0;break;case"object":switch(G.$$typeof){case i:case t:vt=!0;break;case m:return vt=G._init,L(vt(G._payload),j,$,et,ot)}}if(vt)return ot=ot(G),vt=et===""?"."+P(G,0):et,N(ot)?($="",vt!=null&&($=vt.replace(Y,"$&/")+"/"),L(ot,j,$,"",function(_t){return _t})):ot!=null&&(V(ot)&&(ot=B(ot,$+(ot.key==null||G&&G.key===ot.key?"":(""+ot.key).replace(Y,"$&/")+"/")+vt)),j.push(ot)),1;vt=0;var Rt=et===""?".":et+":";if(N(G))for(var Mt=0;Mt>>1,ct=L[at];if(0>>1;atr($,W))etr(ot,$)?(L[at]=ot,L[et]=W,at=et):(L[at]=$,L[j]=W,at=j);else if(etr(ot,W))L[at]=ot,L[et]=W,at=et;else break t}}return H}function r(L,H){var W=L.sortIndex-H.sortIndex;return W!==0?W:L.id-H.id}if(i.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var c=performance;i.unstable_now=function(){return c.now()}}else{var l=Date,d=l.now();i.unstable_now=function(){return l.now()-d}}var h=[],u=[],m=1,g=null,A=3,v=!1,y=!1,w=!1,b=!1,C=typeof setTimeout=="function"?setTimeout:null,S=typeof clearTimeout=="function"?clearTimeout:null,E=typeof setImmediate<"u"?setImmediate:null;function M(L){for(var H=n(u);H!==null;){if(H.callback===null)s(u);else if(H.startTime<=L)s(u),H.sortIndex=H.expirationTime,t(h,H);else break;H=n(u)}}function N(L){if(w=!1,M(L),!y)if(n(h)!==null)y=!0,U||(U=!0,R());else{var H=n(u);H!==null&&X(N,H.startTime-L)}}var U=!1,T=-1,F=5,I=-1;function B(){return b?!0:!(i.unstable_now()-IL&&B());){var at=g.callback;if(typeof at=="function"){g.callback=null,A=g.priorityLevel;var ct=at(g.expirationTime<=L);if(L=i.unstable_now(),typeof ct=="function"){g.callback=ct,M(L),H=!0;break e}g===n(h)&&s(h),M(L)}else s(h);g=n(h)}if(g!==null)H=!0;else{var G=n(u);G!==null&&X(N,G.startTime-L),H=!1}}break t}finally{g=null,A=W,v=!1}H=void 0}}finally{H?R():U=!1}}}var R;if(typeof E=="function")R=function(){E(V)};else if(typeof MessageChannel<"u"){var Y=new MessageChannel,P=Y.port2;Y.port1.onmessage=V,R=function(){P.postMessage(null)}}else R=function(){C(V,0)};function X(L,H){T=C(function(){L(i.unstable_now())},H)}i.unstable_IdlePriority=5,i.unstable_ImmediatePriority=1,i.unstable_LowPriority=4,i.unstable_NormalPriority=3,i.unstable_Profiling=null,i.unstable_UserBlockingPriority=2,i.unstable_cancelCallback=function(L){L.callback=null},i.unstable_forceFrameRate=function(L){0>L||125at?(L.sortIndex=W,t(u,L),n(h)===null&&L===n(u)&&(w?(S(T),T=-1):w=!0,X(N,W-at))):(L.sortIndex=ct,t(h,L),y||v||(y=!0,U||(U=!0,R()))),L},i.unstable_shouldYield=B,i.unstable_wrapCallback=function(L){var H=A;return function(){var W=A;A=H;try{return L.apply(this,arguments)}finally{A=W}}}})(yh)),yh}var Ed;function zA(){return Ed||(Ed=1,xh.exports=OA()),xh.exports}var wh={exports:{}},Ee={};var Dd;function PA(){if(Dd)return Ee;Dd=1;var i=_h();function t(h){var u="https://react.dev/errors/"+h;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(t){console.error(t)}}return i(),wh.exports=PA(),wh.exports}var Ud;function YA(){if(Ud)return Pa;Ud=1;var i=zA(),t=_h(),n=kA();function s(e){var a="https://react.dev/errors/"+e;if(1ct||(e.current=at[ct],at[ct]=null,ct--)}function $(e,a){ct++,at[ct]=e.current,e.current=a}var et=G(null),ot=G(null),mt=G(null),vt=G(null);function Rt(e,a){switch($(mt,a),$(ot,e),$(et,null),a.nodeType){case 9:case 11:e=(e=a.documentElement)&&(e=e.namespaceURI)?q1(e):0;break;default:if(e=a.tagName,a=a.namespaceURI)a=q1(a),e=X1(a,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}j(et),$(et,e)}function Mt(){j(et),j(ot),j(mt)}function _t(e){e.memoizedState!==null&&$(vt,e);var a=et.current,o=X1(a,e.type);a!==o&&($(ot,e),$(et,o))}function ue(e){ot.current===e&&(j(et),j(ot)),vt.current===e&&(j(vt),Na._currentValue=W)}var fe,Jn;function wi(e){if(fe===void 0)try{throw Error()}catch(o){var a=o.stack.trim().match(/\n( *(at )?)/);fe=a&&a[1]||"",Jn=-1)":-1p||q[f]!==_[p]){var it=` +`+q[f].replace(" at new "," at ");return e.displayName&&it.includes("")&&(it=it.replace("",e.displayName)),it}while(1<=f&&0<=p);break}}}finally{Xs=!1,Error.prepareStackTrace=o}return(o=e?e.displayName||e.name:"")?wi(o):""}function $l(e,a){switch(e.tag){case 26:case 27:case 5:return wi(e.type);case 16:return wi("Lazy");case 13:return e.child!==a&&a!==null?wi("Suspense Fallback"):wi("Suspense");case 19:return wi("SuspenseList");case 0:case 15:return rr(e.type,!1);case 11:return rr(e.type.render,!1);case 1:return rr(e.type,!0);case 31:return wi("Activity");default:return""}}function yu(e){try{var a="",o=null;do a+=$l(e,o),o=e,e=e.return;while(e);return a}catch(f){return` +Error generating stack: `+f.message+` +`+f.stack}}var to=Object.prototype.hasOwnProperty,eo=i.unstable_scheduleCallback,io=i.unstable_cancelCallback,um=i.unstable_shouldYield,fm=i.unstable_requestPaint,ke=i.unstable_now,dm=i.unstable_getCurrentPriorityLevel,wu=i.unstable_ImmediatePriority,bu=i.unstable_UserBlockingPriority,lr=i.unstable_NormalPriority,mm=i.unstable_LowPriority,Cu=i.unstable_IdlePriority,gm=i.log,Am=i.unstable_setDisableYieldValue,Ks=null,Ye=null;function Yi(e){if(typeof gm=="function"&&Am(e),Ye&&typeof Ye.setStrictMode=="function")try{Ye.setStrictMode(Ks,e)}catch{}}var Ge=Math.clz32?Math.clz32:xm,pm=Math.log,vm=Math.LN2;function xm(e){return e>>>=0,e===0?32:31-(pm(e)/vm|0)|0}var or=256,cr=262144,hr=4194304;function bn(e){var a=e&42;if(a!==0)return a;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function ur(e,a,o){var f=e.pendingLanes;if(f===0)return 0;var p=0,x=e.suspendedLanes,D=e.pingedLanes;e=e.warmLanes;var O=f&134217727;return O!==0?(f=O&~x,f!==0?p=bn(f):(D&=O,D!==0?p=bn(D):o||(o=O&~e,o!==0&&(p=bn(o))))):(O=f&~x,O!==0?p=bn(O):D!==0?p=bn(D):o||(o=f&~e,o!==0&&(p=bn(o)))),p===0?0:a!==0&&a!==p&&(a&x)===0&&(x=p&-p,o=a&-a,x>=o||x===32&&(o&4194048)!==0)?a:p}function js(e,a){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&a)===0}function ym(e,a){switch(e){case 1:case 2:case 4:case 8:case 64:return a+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return a+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Su(){var e=hr;return hr<<=1,(hr&62914560)===0&&(hr=4194304),e}function no(e){for(var a=[],o=0;31>o;o++)a.push(e);return a}function Qs(e,a){e.pendingLanes|=a,a!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function wm(e,a,o,f,p,x){var D=e.pendingLanes;e.pendingLanes=o,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=o,e.entangledLanes&=o,e.errorRecoveryDisabledLanes&=o,e.shellSuspendCounter=0;var O=e.entanglements,q=e.expirationTimes,_=e.hiddenUpdates;for(o=D&~o;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var Dm=/[\n"\\]/g;function Je(e){return e.replace(Dm,function(a){return"\\"+a.charCodeAt(0).toString(16)+" "})}function co(e,a,o,f,p,x,D,O){e.name="",D!=null&&typeof D!="function"&&typeof D!="symbol"&&typeof D!="boolean"?e.type=D:e.removeAttribute("type"),a!=null?D==="number"?(a===0&&e.value===""||e.value!=a)&&(e.value=""+_e(a)):e.value!==""+_e(a)&&(e.value=""+_e(a)):D!=="submit"&&D!=="reset"||e.removeAttribute("value"),a!=null?ho(e,D,_e(a)):o!=null?ho(e,D,_e(o)):f!=null&&e.removeAttribute("value"),p==null&&x!=null&&(e.defaultChecked=!!x),p!=null&&(e.checked=p&&typeof p!="function"&&typeof p!="symbol"),O!=null&&typeof O!="function"&&typeof O!="symbol"&&typeof O!="boolean"?e.name=""+_e(O):e.removeAttribute("name")}function Ou(e,a,o,f,p,x,D,O){if(x!=null&&typeof x!="function"&&typeof x!="symbol"&&typeof x!="boolean"&&(e.type=x),a!=null||o!=null){if(!(x!=="submit"&&x!=="reset"||a!=null)){oo(e);return}o=o!=null?""+_e(o):"",a=a!=null?""+_e(a):o,O||a===e.value||(e.value=a),e.defaultValue=a}f=f??p,f=typeof f!="function"&&typeof f!="symbol"&&!!f,e.checked=O?e.checked:!!f,e.defaultChecked=!!f,D!=null&&typeof D!="function"&&typeof D!="symbol"&&typeof D!="boolean"&&(e.name=D),oo(e)}function ho(e,a,o){a==="number"&&mr(e.ownerDocument)===e||e.defaultValue===""+o||(e.defaultValue=""+o)}function ss(e,a,o,f){if(e=e.options,a){a={};for(var p=0;p"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Ao=!1;if(Si)try{var Js={};Object.defineProperty(Js,"passive",{get:function(){Ao=!0}}),window.addEventListener("test",Js,Js),window.removeEventListener("test",Js,Js)}catch{Ao=!1}var Hi=null,po=null,Ar=null;function qu(){if(Ar)return Ar;var e,a=po,o=a.length,f,p="value"in Hi?Hi.value:Hi.textContent,x=p.length;for(e=0;e=ea),Wu=" ",_u=!1;function Ju(e,a){switch(e){case"keyup":return eg.indexOf(a.keyCode)!==-1;case"keydown":return a.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function $u(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var os=!1;function ng(e,a){switch(e){case"compositionend":return $u(a);case"keypress":return a.which!==32?null:(_u=!0,Wu);case"textInput":return e=a.data,e===Wu&&_u?null:e;default:return null}}function sg(e,a){if(os)return e==="compositionend"||!bo&&Ju(e,a)?(e=qu(),Ar=po=Hi=null,os=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(a.ctrlKey||a.altKey||a.metaKey)||a.ctrlKey&&a.altKey){if(a.char&&1=a)return{node:o,offset:a-e};e=f}t:{for(;o;){if(o.nextSibling){o=o.nextSibling;break t}o=o.parentNode}o=void 0}o=of(o)}}function hf(e,a){return e&&a?e===a?!0:e&&e.nodeType===3?!1:a&&a.nodeType===3?hf(e,a.parentNode):"contains"in e?e.contains(a):e.compareDocumentPosition?!!(e.compareDocumentPosition(a)&16):!1:!1}function uf(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var a=mr(e.document);a instanceof e.HTMLIFrameElement;){try{var o=typeof a.contentWindow.location.href=="string"}catch{o=!1}if(o)e=a.contentWindow;else break;a=mr(e.document)}return a}function Mo(e){var a=e&&e.nodeName&&e.nodeName.toLowerCase();return a&&(a==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||a==="textarea"||e.contentEditable==="true")}var fg=Si&&"documentMode"in document&&11>=document.documentMode,cs=null,Eo=null,aa=null,Do=!1;function ff(e,a,o){var f=o.window===o?o.document:o.nodeType===9?o:o.ownerDocument;Do||cs==null||cs!==mr(f)||(f=cs,"selectionStart"in f&&Mo(f)?f={start:f.selectionStart,end:f.selectionEnd}:(f=(f.ownerDocument&&f.ownerDocument.defaultView||window).getSelection(),f={anchorNode:f.anchorNode,anchorOffset:f.anchorOffset,focusNode:f.focusNode,focusOffset:f.focusOffset}),aa&&sa(aa,f)||(aa=f,f=cl(Eo,"onSelect"),0>=D,p-=D,Ai=1<<32-Ge(a)+p|o<St?(Bt=gt,gt=null):Bt=gt.sibling;var Vt=J(Q,gt,Z[St],nt);if(Vt===null){gt===null&&(gt=Bt);break}e&>&&Vt.alternate===null&&a(Q,gt),K=x(Vt,K,St),Nt===null?pt=Vt:Nt.sibling=Vt,Nt=Vt,gt=Bt}if(St===Z.length)return o(Q,gt),It&&Ei(Q,St),pt;if(gt===null){for(;StSt?(Bt=gt,gt=null):Bt=gt.sibling;var fn=J(Q,gt,Vt.value,nt);if(fn===null){gt===null&&(gt=Bt);break}e&>&&fn.alternate===null&&a(Q,gt),K=x(fn,K,St),Nt===null?pt=fn:Nt.sibling=fn,Nt=fn,gt=Bt}if(Vt.done)return o(Q,gt),It&&Ei(Q,St),pt;if(gt===null){for(;!Vt.done;St++,Vt=Z.next())Vt=st(Q,Vt.value,nt),Vt!==null&&(K=x(Vt,K,St),Nt===null?pt=Vt:Nt.sibling=Vt,Nt=Vt);return It&&Ei(Q,St),pt}for(gt=f(gt);!Vt.done;St++,Vt=Z.next())Vt=tt(gt,Q,St,Vt.value,nt),Vt!==null&&(e&&Vt.alternate!==null&>.delete(Vt.key===null?St:Vt.key),K=x(Vt,K,St),Nt===null?pt=Vt:Nt.sibling=Vt,Nt=Vt);return e&>.forEach(function(IA){return a(Q,IA)}),It&&Ei(Q,St),pt}function Xt(Q,K,Z,nt){if(typeof Z=="object"&&Z!==null&&Z.type===w&&Z.key===null&&(Z=Z.props.children),typeof Z=="object"&&Z!==null){switch(Z.$$typeof){case v:t:{for(var pt=Z.key;K!==null;){if(K.key===pt){if(pt=Z.type,pt===w){if(K.tag===7){o(Q,K.sibling),nt=p(K,Z.props.children),nt.return=Q,Q=nt;break t}}else if(K.elementType===pt||typeof pt=="object"&&pt!==null&&pt.$$typeof===F&&Rn(pt)===K.type){o(Q,K.sibling),nt=p(K,Z.props),ua(nt,Z),nt.return=Q,Q=nt;break t}o(Q,K);break}else a(Q,K);K=K.sibling}Z.type===w?(nt=Tn(Z.props.children,Q.mode,nt,Z.key),nt.return=Q,Q=nt):(nt=Er(Z.type,Z.key,Z.props,null,Q.mode,nt),ua(nt,Z),nt.return=Q,Q=nt)}return D(Q);case y:t:{for(pt=Z.key;K!==null;){if(K.key===pt)if(K.tag===4&&K.stateNode.containerInfo===Z.containerInfo&&K.stateNode.implementation===Z.implementation){o(Q,K.sibling),nt=p(K,Z.children||[]),nt.return=Q,Q=nt;break t}else{o(Q,K);break}else a(Q,K);K=K.sibling}nt=No(Z,Q.mode,nt),nt.return=Q,Q=nt}return D(Q);case F:return Z=Rn(Z),Xt(Q,K,Z,nt)}if(X(Z))return ft(Q,K,Z,nt);if(R(Z)){if(pt=R(Z),typeof pt!="function")throw Error(s(150));return Z=pt.call(Z),xt(Q,K,Z,nt)}if(typeof Z.then=="function")return Xt(Q,K,Rr(Z),nt);if(Z.$$typeof===E)return Xt(Q,K,Ur(Q,Z),nt);Nr(Q,Z)}return typeof Z=="string"&&Z!==""||typeof Z=="number"||typeof Z=="bigint"?(Z=""+Z,K!==null&&K.tag===6?(o(Q,K.sibling),nt=p(K,Z),nt.return=Q,Q=nt):(o(Q,K),nt=Ro(Z,Q.mode,nt),nt.return=Q,Q=nt),D(Q)):o(Q,K)}return function(Q,K,Z,nt){try{ha=0;var pt=Xt(Q,K,Z,nt);return ys=null,pt}catch(gt){if(gt===xs||gt===Br)throw gt;var Nt=qe(29,gt,null,Q.mode);return Nt.lanes=nt,Nt.return=Q,Nt}finally{}}}var Vn=Vf(!0),Lf=Vf(!1),Qi=!1;function Ko(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function jo(e,a){e=e.updateQueue,a.updateQueue===e&&(a.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Zi(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Wi(e,a,o){var f=e.updateQueue;if(f===null)return null;if(f=f.shared,(zt&2)!==0){var p=f.pending;return p===null?a.next=a:(a.next=p.next,p.next=a),f.pending=a,a=Mr(e),xf(e,null,o),a}return Sr(e,f,a,o),Mr(e)}function fa(e,a,o){if(a=a.updateQueue,a!==null&&(a=a.shared,(o&4194048)!==0)){var f=a.lanes;f&=e.pendingLanes,o|=f,a.lanes=o,Eu(e,o)}}function Qo(e,a){var o=e.updateQueue,f=e.alternate;if(f!==null&&(f=f.updateQueue,o===f)){var p=null,x=null;if(o=o.firstBaseUpdate,o!==null){do{var D={lane:o.lane,tag:o.tag,payload:o.payload,callback:null,next:null};x===null?p=x=D:x=x.next=D,o=o.next}while(o!==null);x===null?p=x=a:x=x.next=a}else p=x=a;o={baseState:f.baseState,firstBaseUpdate:p,lastBaseUpdate:x,shared:f.shared,callbacks:f.callbacks},e.updateQueue=o;return}e=o.lastBaseUpdate,e===null?o.firstBaseUpdate=a:e.next=a,o.lastBaseUpdate=a}var Zo=!1;function da(){if(Zo){var e=vs;if(e!==null)throw e}}function ma(e,a,o,f){Zo=!1;var p=e.updateQueue;Qi=!1;var x=p.firstBaseUpdate,D=p.lastBaseUpdate,O=p.shared.pending;if(O!==null){p.shared.pending=null;var q=O,_=q.next;q.next=null,D===null?x=_:D.next=_,D=q;var it=e.alternate;it!==null&&(it=it.updateQueue,O=it.lastBaseUpdate,O!==D&&(O===null?it.firstBaseUpdate=_:O.next=_,it.lastBaseUpdate=q))}if(x!==null){var st=p.baseState;D=0,it=_=q=null,O=x;do{var J=O.lane&-536870913,tt=J!==O.lane;if(tt?(Ft&J)===J:(f&J)===J){J!==0&&J===ps&&(Zo=!0),it!==null&&(it=it.next={lane:0,tag:O.tag,payload:O.payload,callback:null,next:null});t:{var ft=e,xt=O;J=a;var Xt=o;switch(xt.tag){case 1:if(ft=xt.payload,typeof ft=="function"){st=ft.call(Xt,st,J);break t}st=ft;break t;case 3:ft.flags=ft.flags&-65537|128;case 0:if(ft=xt.payload,J=typeof ft=="function"?ft.call(Xt,st,J):ft,J==null)break t;st=g({},st,J);break t;case 2:Qi=!0}}J=O.callback,J!==null&&(e.flags|=64,tt&&(e.flags|=8192),tt=p.callbacks,tt===null?p.callbacks=[J]:tt.push(J))}else tt={lane:J,tag:O.tag,payload:O.payload,callback:O.callback,next:null},it===null?(_=it=tt,q=st):it=it.next=tt,D|=J;if(O=O.next,O===null){if(O=p.shared.pending,O===null)break;tt=O,O=tt.next,tt.next=null,p.lastBaseUpdate=tt,p.shared.pending=null}}while(!0);it===null&&(q=st),p.baseState=q,p.firstBaseUpdate=_,p.lastBaseUpdate=it,x===null&&(p.shared.lanes=0),en|=D,e.lanes=D,e.memoizedState=st}}function Of(e,a){if(typeof e!="function")throw Error(s(191,e));e.call(a)}function zf(e,a){var o=e.callbacks;if(o!==null)for(e.callbacks=null,e=0;ex?x:8;var D=L.T,O={};L.T=O,mc(e,!1,a,o);try{var q=p(),_=L.S;if(_!==null&&_(O,q),q!==null&&typeof q=="object"&&typeof q.then=="function"){var it=wg(q,f);pa(e,a,it,Ze(e))}else pa(e,a,f,Ze(e))}catch(st){pa(e,a,{then:function(){},status:"rejected",reason:st},Ze())}finally{H.p=x,D!==null&&O.types!==null&&(D.types=O.types),L.T=D}}function Dg(){}function fc(e,a,o,f){if(e.tag!==5)throw Error(s(476));var p=A0(e).queue;g0(e,p,a,W,o===null?Dg:function(){return p0(e),o(f)})}function A0(e){var a=e.memoizedState;if(a!==null)return a;a={memoizedState:W,baseState:W,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Fi,lastRenderedState:W},next:null};var o={};return a.next={memoizedState:o,baseState:o,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Fi,lastRenderedState:o},next:null},e.memoizedState=a,e=e.alternate,e!==null&&(e.memoizedState=a),a}function p0(e){var a=A0(e);a.next===null&&(a=e.alternate.memoizedState),pa(e,a.next.queue,{},Ze())}function dc(){return be(Na)}function v0(){return ae().memoizedState}function x0(){return ae().memoizedState}function Tg(e){for(var a=e.return;a!==null;){switch(a.tag){case 24:case 3:var o=Ze();e=Zi(o);var f=Wi(a,e,o);f!==null&&(Oe(f,a,o),fa(f,a,o)),a={cache:Go()},e.payload=a;return}a=a.return}}function Ug(e,a,o){var f=Ze();o={lane:f,revertLane:0,gesture:null,action:o,hasEagerState:!1,eagerState:null,next:null},qr(e)?w0(a,o):(o=Bo(e,a,o,f),o!==null&&(Oe(o,e,f),b0(o,a,f)))}function y0(e,a,o){var f=Ze();pa(e,a,o,f)}function pa(e,a,o,f){var p={lane:f,revertLane:0,gesture:null,action:o,hasEagerState:!1,eagerState:null,next:null};if(qr(e))w0(a,p);else{var x=e.alternate;if(e.lanes===0&&(x===null||x.lanes===0)&&(x=a.lastRenderedReducer,x!==null))try{var D=a.lastRenderedState,O=x(D,o);if(p.hasEagerState=!0,p.eagerState=O,He(O,D))return Sr(e,a,p,0),Kt===null&&Cr(),!1}catch{}finally{}if(o=Bo(e,a,p,f),o!==null)return Oe(o,e,f),b0(o,a,f),!0}return!1}function mc(e,a,o,f){if(f={lane:2,revertLane:Kc(),gesture:null,action:f,hasEagerState:!1,eagerState:null,next:null},qr(e)){if(a)throw Error(s(479))}else a=Bo(e,o,f,2),a!==null&&Oe(a,e,2)}function qr(e){var a=e.alternate;return e===Ct||a!==null&&a===Ct}function w0(e,a){bs=Or=!0;var o=e.pending;o===null?a.next=a:(a.next=o.next,o.next=a),e.pending=a}function b0(e,a,o){if((o&4194048)!==0){var f=a.lanes;f&=e.pendingLanes,o|=f,a.lanes=o,Eu(e,o)}}var va={readContext:be,use:kr,useCallback:ee,useContext:ee,useEffect:ee,useImperativeHandle:ee,useLayoutEffect:ee,useInsertionEffect:ee,useMemo:ee,useReducer:ee,useRef:ee,useState:ee,useDebugValue:ee,useDeferredValue:ee,useTransition:ee,useSyncExternalStore:ee,useId:ee,useHostTransitionStatus:ee,useFormState:ee,useActionState:ee,useOptimistic:ee,useMemoCache:ee,useCacheRefresh:ee};va.useEffectEvent=ee;var C0={readContext:be,use:kr,useCallback:function(e,a){return Te().memoizedState=[e,a===void 0?null:a],e},useContext:be,useEffect:r0,useImperativeHandle:function(e,a,o){o=o!=null?o.concat([e]):null,Gr(4194308,4,h0.bind(null,a,e),o)},useLayoutEffect:function(e,a){return Gr(4194308,4,e,a)},useInsertionEffect:function(e,a){Gr(4,2,e,a)},useMemo:function(e,a){var o=Te();a=a===void 0?null:a;var f=e();if(Ln){Yi(!0);try{e()}finally{Yi(!1)}}return o.memoizedState=[f,a],f},useReducer:function(e,a,o){var f=Te();if(o!==void 0){var p=o(a);if(Ln){Yi(!0);try{o(a)}finally{Yi(!1)}}}else p=a;return f.memoizedState=f.baseState=p,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:p},f.queue=e,e=e.dispatch=Ug.bind(null,Ct,e),[f.memoizedState,e]},useRef:function(e){var a=Te();return e={current:e},a.memoizedState=e},useState:function(e){e=lc(e);var a=e.queue,o=y0.bind(null,Ct,a);return a.dispatch=o,[e.memoizedState,o]},useDebugValue:hc,useDeferredValue:function(e,a){var o=Te();return uc(o,e,a)},useTransition:function(){var e=lc(!1);return e=g0.bind(null,Ct,e.queue,!0,!1),Te().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,a,o){var f=Ct,p=Te();if(It){if(o===void 0)throw Error(s(407));o=o()}else{if(o=a(),Kt===null)throw Error(s(349));(Ft&127)!==0||qf(f,a,o)}p.memoizedState=o;var x={value:o,getSnapshot:a};return p.queue=x,r0(Kf.bind(null,f,x,e),[e]),f.flags|=2048,Ss(9,{destroy:void 0},Xf.bind(null,f,x,o,a),null),o},useId:function(){var e=Te(),a=Kt.identifierPrefix;if(It){var o=pi,f=Ai;o=(f&~(1<<32-Ge(f)-1)).toString(32)+o,a="_"+a+"R_"+o,o=zr++,0<\/script>",x=x.removeChild(x.firstChild);break;case"select":x=typeof f.is=="string"?D.createElement("select",{is:f.is}):D.createElement("select"),f.multiple?x.multiple=!0:f.size&&(x.size=f.size);break;default:x=typeof f.is=="string"?D.createElement(p,{is:f.is}):D.createElement(p)}}x[ye]=a,x[Be]=f;t:for(D=a.child;D!==null;){if(D.tag===5||D.tag===6)x.appendChild(D.stateNode);else if(D.tag!==4&&D.tag!==27&&D.child!==null){D.child.return=D,D=D.child;continue}if(D===a)break t;for(;D.sibling===null;){if(D.return===null||D.return===a)break t;D=D.return}D.sibling.return=D.return,D=D.sibling}a.stateNode=x;t:switch(Se(x,p,f),p){case"button":case"input":case"select":case"textarea":f=!!f.autoFocus;break t;case"img":f=!0;break t;default:f=!1}f&&Ii(a)}}return Zt(a),Tc(a,a.type,e===null?null:e.memoizedProps,a.pendingProps,o),null;case 6:if(e&&a.stateNode!=null)e.memoizedProps!==f&&Ii(a);else{if(typeof f!="string"&&a.stateNode===null)throw Error(s(166));if(e=mt.current,gs(a)){if(e=a.stateNode,o=a.memoizedProps,f=null,p=we,p!==null)switch(p.tag){case 27:case 5:f=p.memoizedProps}e[ye]=a,e=!!(e.nodeValue===o||f!==null&&f.suppressHydrationWarning===!0||G1(e.nodeValue,o)),e||Ki(a,!0)}else e=hl(e).createTextNode(f),e[ye]=a,a.stateNode=e}return Zt(a),null;case 31:if(o=a.memoizedState,e===null||e.memoizedState!==null){if(f=gs(a),o!==null){if(e===null){if(!f)throw Error(s(318));if(e=a.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(s(557));e[ye]=a}else Un(),(a.flags&128)===0&&(a.memoizedState=null),a.flags|=4;Zt(a),e=!1}else o=zo(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=o),e=!0;if(!e)return a.flags&256?(Ke(a),a):(Ke(a),null);if((a.flags&128)!==0)throw Error(s(558))}return Zt(a),null;case 13:if(f=a.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(p=gs(a),f!==null&&f.dehydrated!==null){if(e===null){if(!p)throw Error(s(318));if(p=a.memoizedState,p=p!==null?p.dehydrated:null,!p)throw Error(s(317));p[ye]=a}else Un(),(a.flags&128)===0&&(a.memoizedState=null),a.flags|=4;Zt(a),p=!1}else p=zo(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=p),p=!0;if(!p)return a.flags&256?(Ke(a),a):(Ke(a),null)}return Ke(a),(a.flags&128)!==0?(a.lanes=o,a):(o=f!==null,e=e!==null&&e.memoizedState!==null,o&&(f=a.child,p=null,f.alternate!==null&&f.alternate.memoizedState!==null&&f.alternate.memoizedState.cachePool!==null&&(p=f.alternate.memoizedState.cachePool.pool),x=null,f.memoizedState!==null&&f.memoizedState.cachePool!==null&&(x=f.memoizedState.cachePool.pool),x!==p&&(f.flags|=2048)),o!==e&&o&&(a.child.flags|=8192),Zr(a,a.updateQueue),Zt(a),null);case 4:return Mt(),e===null&&Wc(a.stateNode.containerInfo),Zt(a),null;case 10:return Ti(a.type),Zt(a),null;case 19:if(j(se),f=a.memoizedState,f===null)return Zt(a),null;if(p=(a.flags&128)!==0,x=f.rendering,x===null)if(p)ya(f,!1);else{if(ie!==0||e!==null&&(e.flags&128)!==0)for(e=a.child;e!==null;){if(x=Lr(e),x!==null){for(a.flags|=128,ya(f,!1),e=x.updateQueue,a.updateQueue=e,Zr(a,e),a.subtreeFlags=0,e=o,o=a.child;o!==null;)yf(o,e),o=o.sibling;return $(se,se.current&1|2),It&&Ei(a,f.treeForkCount),a.child}e=e.sibling}f.tail!==null&&ke()>tl&&(a.flags|=128,p=!0,ya(f,!1),a.lanes=4194304)}else{if(!p)if(e=Lr(x),e!==null){if(a.flags|=128,p=!0,e=e.updateQueue,a.updateQueue=e,Zr(a,e),ya(f,!0),f.tail===null&&f.tailMode==="hidden"&&!x.alternate&&!It)return Zt(a),null}else 2*ke()-f.renderingStartTime>tl&&o!==536870912&&(a.flags|=128,p=!0,ya(f,!1),a.lanes=4194304);f.isBackwards?(x.sibling=a.child,a.child=x):(e=f.last,e!==null?e.sibling=x:a.child=x,f.last=x)}return f.tail!==null?(e=f.tail,f.rendering=e,f.tail=e.sibling,f.renderingStartTime=ke(),e.sibling=null,o=se.current,$(se,p?o&1|2:o&1),It&&Ei(a,f.treeForkCount),e):(Zt(a),null);case 22:case 23:return Ke(a),_o(),f=a.memoizedState!==null,e!==null?e.memoizedState!==null!==f&&(a.flags|=8192):f&&(a.flags|=8192),f?(o&536870912)!==0&&(a.flags&128)===0&&(Zt(a),a.subtreeFlags&6&&(a.flags|=8192)):Zt(a),o=a.updateQueue,o!==null&&Zr(a,o.retryQueue),o=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(o=e.memoizedState.cachePool.pool),f=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(f=a.memoizedState.cachePool.pool),f!==o&&(a.flags|=2048),e!==null&&j(In),null;case 24:return o=null,e!==null&&(o=e.memoizedState.cache),a.memoizedState.cache!==o&&(a.flags|=2048),Ti(le),Zt(a),null;case 25:return null;case 30:return null}throw Error(s(156,a.tag))}function Ng(e,a){switch(Lo(a),a.tag){case 1:return e=a.flags,e&65536?(a.flags=e&-65537|128,a):null;case 3:return Ti(le),Mt(),e=a.flags,(e&65536)!==0&&(e&128)===0?(a.flags=e&-65537|128,a):null;case 26:case 27:case 5:return ue(a),null;case 31:if(a.memoizedState!==null){if(Ke(a),a.alternate===null)throw Error(s(340));Un()}return e=a.flags,e&65536?(a.flags=e&-65537|128,a):null;case 13:if(Ke(a),e=a.memoizedState,e!==null&&e.dehydrated!==null){if(a.alternate===null)throw Error(s(340));Un()}return e=a.flags,e&65536?(a.flags=e&-65537|128,a):null;case 19:return j(se),null;case 4:return Mt(),null;case 10:return Ti(a.type),null;case 22:case 23:return Ke(a),_o(),e!==null&&j(In),e=a.flags,e&65536?(a.flags=e&-65537|128,a):null;case 24:return Ti(le),null;case 25:return null;default:return null}}function j0(e,a){switch(Lo(a),a.tag){case 3:Ti(le),Mt();break;case 26:case 27:case 5:ue(a);break;case 4:Mt();break;case 31:a.memoizedState!==null&&Ke(a);break;case 13:Ke(a);break;case 19:j(se);break;case 10:Ti(a.type);break;case 22:case 23:Ke(a),_o(),e!==null&&j(In);break;case 24:Ti(le)}}function wa(e,a){try{var o=a.updateQueue,f=o!==null?o.lastEffect:null;if(f!==null){var p=f.next;o=p;do{if((o.tag&e)===e){f=void 0;var x=o.create,D=o.inst;f=x(),D.destroy=f}o=o.next}while(o!==p)}}catch(O){Yt(a,a.return,O)}}function $i(e,a,o){try{var f=a.updateQueue,p=f!==null?f.lastEffect:null;if(p!==null){var x=p.next;f=x;do{if((f.tag&e)===e){var D=f.inst,O=D.destroy;if(O!==void 0){D.destroy=void 0,p=a;var q=o,_=O;try{_()}catch(it){Yt(p,q,it)}}}f=f.next}while(f!==x)}}catch(it){Yt(a,a.return,it)}}function Q0(e){var a=e.updateQueue;if(a!==null){var o=e.stateNode;try{zf(a,o)}catch(f){Yt(e,e.return,f)}}}function Z0(e,a,o){o.props=On(e.type,e.memoizedProps),o.state=e.memoizedState;try{o.componentWillUnmount()}catch(f){Yt(e,a,f)}}function ba(e,a){try{var o=e.ref;if(o!==null){switch(e.tag){case 26:case 27:case 5:var f=e.stateNode;break;case 30:f=e.stateNode;break;default:f=e.stateNode}typeof o=="function"?e.refCleanup=o(f):o.current=f}}catch(p){Yt(e,a,p)}}function vi(e,a){var o=e.ref,f=e.refCleanup;if(o!==null)if(typeof f=="function")try{f()}catch(p){Yt(e,a,p)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof o=="function")try{o(null)}catch(p){Yt(e,a,p)}else o.current=null}function W0(e){var a=e.type,o=e.memoizedProps,f=e.stateNode;try{t:switch(a){case"button":case"input":case"select":case"textarea":o.autoFocus&&f.focus();break t;case"img":o.src?f.src=o.src:o.srcSet&&(f.srcset=o.srcSet)}}catch(p){Yt(e,e.return,p)}}function Uc(e,a,o){try{var f=e.stateNode;iA(f,e.type,o,a),f[Be]=a}catch(p){Yt(e,e.return,p)}}function _0(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&ln(e.type)||e.tag===4}function Fc(e){t:for(;;){for(;e.sibling===null;){if(e.return===null||_0(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&ln(e.type)||e.flags&2||e.child===null||e.tag===4)continue t;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Bc(e,a,o){var f=e.tag;if(f===5||f===6)e=e.stateNode,a?(o.nodeType===9?o.body:o.nodeName==="HTML"?o.ownerDocument.body:o).insertBefore(e,a):(a=o.nodeType===9?o.body:o.nodeName==="HTML"?o.ownerDocument.body:o,a.appendChild(e),o=o._reactRootContainer,o!=null||a.onclick!==null||(a.onclick=Ci));else if(f!==4&&(f===27&&ln(e.type)&&(o=e.stateNode,a=null),e=e.child,e!==null))for(Bc(e,a,o),e=e.sibling;e!==null;)Bc(e,a,o),e=e.sibling}function Wr(e,a,o){var f=e.tag;if(f===5||f===6)e=e.stateNode,a?o.insertBefore(e,a):o.appendChild(e);else if(f!==4&&(f===27&&ln(e.type)&&(o=e.stateNode),e=e.child,e!==null))for(Wr(e,a,o),e=e.sibling;e!==null;)Wr(e,a,o),e=e.sibling}function J0(e){var a=e.stateNode,o=e.memoizedProps;try{for(var f=e.type,p=a.attributes;p.length;)a.removeAttributeNode(p[0]);Se(a,f,o),a[ye]=e,a[Be]=o}catch(x){Yt(e,e.return,x)}}var Ri=!1,he=!1,Ic=!1,$0=typeof WeakSet=="function"?WeakSet:Set,pe=null;function Vg(e,a){if(e=e.containerInfo,$c=pl,e=uf(e),Mo(e)){if("selectionStart"in e)var o={start:e.selectionStart,end:e.selectionEnd};else t:{o=(o=e.ownerDocument)&&o.defaultView||window;var f=o.getSelection&&o.getSelection();if(f&&f.rangeCount!==0){o=f.anchorNode;var p=f.anchorOffset,x=f.focusNode;f=f.focusOffset;try{o.nodeType,x.nodeType}catch{o=null;break t}var D=0,O=-1,q=-1,_=0,it=0,st=e,J=null;e:for(;;){for(var tt;st!==o||p!==0&&st.nodeType!==3||(O=D+p),st!==x||f!==0&&st.nodeType!==3||(q=D+f),st.nodeType===3&&(D+=st.nodeValue.length),(tt=st.firstChild)!==null;)J=st,st=tt;for(;;){if(st===e)break e;if(J===o&&++_===p&&(O=D),J===x&&++it===f&&(q=D),(tt=st.nextSibling)!==null)break;st=J,J=st.parentNode}st=tt}o=O===-1||q===-1?null:{start:O,end:q}}else o=null}o=o||{start:0,end:0}}else o=null;for(th={focusedElem:e,selectionRange:o},pl=!1,pe=a;pe!==null;)if(a=pe,e=a.child,(a.subtreeFlags&1028)!==0&&e!==null)e.return=a,pe=e;else for(;pe!==null;){switch(a=pe,x=a.alternate,e=a.flags,a.tag){case 0:if((e&4)!==0&&(e=a.updateQueue,e=e!==null?e.events:null,e!==null))for(o=0;o title"))),Se(x,f,o),x[ye]=e,Ae(x),f=x;break t;case"link":var D=ad("link","href",p).get(f+(o.href||""));if(D){for(var O=0;OXt&&(D=Xt,Xt=xt,xt=D);var Q=cf(O,xt),K=cf(O,Xt);if(Q&&K&&(tt.rangeCount!==1||tt.anchorNode!==Q.node||tt.anchorOffset!==Q.offset||tt.focusNode!==K.node||tt.focusOffset!==K.offset)){var Z=st.createRange();Z.setStart(Q.node,Q.offset),tt.removeAllRanges(),xt>Xt?(tt.addRange(Z),tt.extend(K.node,K.offset)):(Z.setEnd(K.node,K.offset),tt.addRange(Z))}}}}for(st=[],tt=O;tt=tt.parentNode;)tt.nodeType===1&&st.push({element:tt,left:tt.scrollLeft,top:tt.scrollTop});for(typeof O.focus=="function"&&O.focus(),O=0;Oo?32:o,L.T=null,o=Pc,Pc=null;var x=sn,D=zi;if(de=0,Us=sn=null,zi=0,(zt&6)!==0)throw Error(s(331));var O=zt;if(zt|=4,h1(x.current),l1(x,x.current,D,o),zt=O,Ta(0,!1),Ye&&typeof Ye.onPostCommitFiberRoot=="function")try{Ye.onPostCommitFiberRoot(Ks,x)}catch{}return!0}finally{H.p=p,L.T=f,T1(e,a)}}function F1(e,a,o){a=ti(o,a),a=vc(e.stateNode,a,2),e=Wi(e,a,2),e!==null&&(Qs(e,2),xi(e))}function Yt(e,a,o){if(e.tag===3)F1(e,e,o);else for(;a!==null;){if(a.tag===3){F1(a,e,o);break}else if(a.tag===1){var f=a.stateNode;if(typeof a.type.getDerivedStateFromError=="function"||typeof f.componentDidCatch=="function"&&(nn===null||!nn.has(f))){e=ti(o,e),o=B0(2),f=Wi(a,o,2),f!==null&&(I0(o,f,a,e),Qs(f,2),xi(f));break}}a=a.return}}function Hc(e,a,o){var f=e.pingCache;if(f===null){f=e.pingCache=new zg;var p=new Set;f.set(a,p)}else p=f.get(a),p===void 0&&(p=new Set,f.set(a,p));p.has(o)||(Vc=!0,p.add(o),e=Hg.bind(null,e,a,o),a.then(e,e))}function Hg(e,a,o){var f=e.pingCache;f!==null&&f.delete(a),e.pingedLanes|=e.suspendedLanes&o,e.warmLanes&=~o,Kt===e&&(Ft&o)===o&&(ie===4||ie===3&&(Ft&62914560)===Ft&&300>ke()-$r?(zt&2)===0&&Fs(e,0):Lc|=o,Ts===Ft&&(Ts=0)),xi(e)}function B1(e,a){a===0&&(a=Su()),e=Dn(e,a),e!==null&&(Qs(e,a),xi(e))}function qg(e){var a=e.memoizedState,o=0;a!==null&&(o=a.retryLane),B1(e,o)}function Xg(e,a){var o=0;switch(e.tag){case 31:case 13:var f=e.stateNode,p=e.memoizedState;p!==null&&(o=p.retryLane);break;case 19:f=e.stateNode;break;case 22:f=e.stateNode._retryCache;break;default:throw Error(s(314))}f!==null&&f.delete(a),B1(e,o)}function Kg(e,a){return eo(e,a)}var rl=null,Is=null,qc=!1,ll=!1,Xc=!1,rn=0;function xi(e){e!==Is&&e.next===null&&(Is===null?rl=Is=e:Is=Is.next=e),ll=!0,qc||(qc=!0,Qg())}function Ta(e,a){if(!Xc&&ll){Xc=!0;do for(var o=!1,f=rl;f!==null;){if(e!==0){var p=f.pendingLanes;if(p===0)var x=0;else{var D=f.suspendedLanes,O=f.pingedLanes;x=(1<<31-Ge(42|e)+1)-1,x&=p&~(D&~O),x=x&201326741?x&201326741|1:x?x|2:0}x!==0&&(o=!0,V1(f,x))}else x=Ft,x=ur(f,f===Kt?x:0,f.cancelPendingCommit!==null||f.timeoutHandle!==-1),(x&3)===0||js(f,x)||(o=!0,V1(f,x));f=f.next}while(o);Xc=!1}}function jg(){I1()}function I1(){ll=qc=!1;var e=0;rn!==0&&sA()&&(e=rn);for(var a=ke(),o=null,f=rl;f!==null;){var p=f.next,x=R1(f,a);x===0?(f.next=null,o===null?rl=p:o.next=p,p===null&&(Is=o)):(o=f,(e!==0||(x&3)!==0)&&(ll=!0)),f=p}de!==0&&de!==5||Ta(e),rn!==0&&(rn=0)}function R1(e,a){for(var o=e.suspendedLanes,f=e.pingedLanes,p=e.expirationTimes,x=e.pendingLanes&-62914561;0O)break;var it=q.transferSize,st=q.initiatorType;it&&H1(st)&&(q=q.responseEnd,D+=it*(q"u"?null:document;function ed(e,a,o){var f=Rs;if(f&&typeof a=="string"&&a){var p=Je(a);p='link[rel="'+e+'"][href="'+p+'"]',typeof o=="string"&&(p+='[crossorigin="'+o+'"]'),td.has(p)||(td.add(p),e={rel:e,crossOrigin:o,href:a},f.querySelector(p)===null&&(a=f.createElement("link"),Se(a,"link",e),Ae(a),f.head.appendChild(a)))}}function dA(e){Pi.D(e),ed("dns-prefetch",e,null)}function mA(e,a){Pi.C(e,a),ed("preconnect",e,a)}function gA(e,a,o){Pi.L(e,a,o);var f=Rs;if(f&&e&&a){var p='link[rel="preload"][as="'+Je(a)+'"]';a==="image"&&o&&o.imageSrcSet?(p+='[imagesrcset="'+Je(o.imageSrcSet)+'"]',typeof o.imageSizes=="string"&&(p+='[imagesizes="'+Je(o.imageSizes)+'"]')):p+='[href="'+Je(e)+'"]';var x=p;switch(a){case"style":x=Ns(e);break;case"script":x=Vs(e)}ri.has(x)||(e=g({rel:"preload",href:a==="image"&&o&&o.imageSrcSet?void 0:e,as:a},o),ri.set(x,e),f.querySelector(p)!==null||a==="style"&&f.querySelector(Ia(x))||a==="script"&&f.querySelector(Ra(x))||(a=f.createElement("link"),Se(a,"link",e),Ae(a),f.head.appendChild(a)))}}function AA(e,a){Pi.m(e,a);var o=Rs;if(o&&e){var f=a&&typeof a.as=="string"?a.as:"script",p='link[rel="modulepreload"][as="'+Je(f)+'"][href="'+Je(e)+'"]',x=p;switch(f){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":x=Vs(e)}if(!ri.has(x)&&(e=g({rel:"modulepreload",href:e},a),ri.set(x,e),o.querySelector(p)===null)){switch(f){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(o.querySelector(Ra(x)))return}f=o.createElement("link"),Se(f,"link",e),Ae(f),o.head.appendChild(f)}}}function pA(e,a,o){Pi.S(e,a,o);var f=Rs;if(f&&e){var p=is(f).hoistableStyles,x=Ns(e);a=a||"default";var D=p.get(x);if(!D){var O={loading:0,preload:null};if(D=f.querySelector(Ia(x)))O.loading=5;else{e=g({rel:"stylesheet",href:e,"data-precedence":a},o),(o=ri.get(x))&&lh(e,o);var q=D=f.createElement("link");Ae(q),Se(q,"link",e),q._p=new Promise(function(_,it){q.onload=_,q.onerror=it}),q.addEventListener("load",function(){O.loading|=1}),q.addEventListener("error",function(){O.loading|=2}),O.loading|=4,fl(D,a,f)}D={type:"stylesheet",instance:D,count:1,state:O},p.set(x,D)}}}function vA(e,a){Pi.X(e,a);var o=Rs;if(o&&e){var f=is(o).hoistableScripts,p=Vs(e),x=f.get(p);x||(x=o.querySelector(Ra(p)),x||(e=g({src:e,async:!0},a),(a=ri.get(p))&&oh(e,a),x=o.createElement("script"),Ae(x),Se(x,"link",e),o.head.appendChild(x)),x={type:"script",instance:x,count:1,state:null},f.set(p,x))}}function xA(e,a){Pi.M(e,a);var o=Rs;if(o&&e){var f=is(o).hoistableScripts,p=Vs(e),x=f.get(p);x||(x=o.querySelector(Ra(p)),x||(e=g({src:e,async:!0,type:"module"},a),(a=ri.get(p))&&oh(e,a),x=o.createElement("script"),Ae(x),Se(x,"link",e),o.head.appendChild(x)),x={type:"script",instance:x,count:1,state:null},f.set(p,x))}}function id(e,a,o,f){var p=(p=mt.current)?ul(p):null;if(!p)throw Error(s(446));switch(e){case"meta":case"title":return null;case"style":return typeof o.precedence=="string"&&typeof o.href=="string"?(a=Ns(o.href),o=is(p).hoistableStyles,f=o.get(a),f||(f={type:"style",instance:null,count:0,state:null},o.set(a,f)),f):{type:"void",instance:null,count:0,state:null};case"link":if(o.rel==="stylesheet"&&typeof o.href=="string"&&typeof o.precedence=="string"){e=Ns(o.href);var x=is(p).hoistableStyles,D=x.get(e);if(D||(p=p.ownerDocument||p,D={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},x.set(e,D),(x=p.querySelector(Ia(e)))&&!x._p&&(D.instance=x,D.state.loading=5),ri.has(e)||(o={rel:"preload",as:"style",href:o.href,crossOrigin:o.crossOrigin,integrity:o.integrity,media:o.media,hrefLang:o.hrefLang,referrerPolicy:o.referrerPolicy},ri.set(e,o),x||yA(p,e,o,D.state))),a&&f===null)throw Error(s(528,""));return D}if(a&&f!==null)throw Error(s(529,""));return null;case"script":return a=o.async,o=o.src,typeof o=="string"&&a&&typeof a!="function"&&typeof a!="symbol"?(a=Vs(o),o=is(p).hoistableScripts,f=o.get(a),f||(f={type:"script",instance:null,count:0,state:null},o.set(a,f)),f):{type:"void",instance:null,count:0,state:null};default:throw Error(s(444,e))}}function Ns(e){return'href="'+Je(e)+'"'}function Ia(e){return'link[rel="stylesheet"]['+e+"]"}function nd(e){return g({},e,{"data-precedence":e.precedence,precedence:null})}function yA(e,a,o,f){e.querySelector('link[rel="preload"][as="style"]['+a+"]")?f.loading=1:(a=e.createElement("link"),f.preload=a,a.addEventListener("load",function(){return f.loading|=1}),a.addEventListener("error",function(){return f.loading|=2}),Se(a,"link",o),Ae(a),e.head.appendChild(a))}function Vs(e){return'[src="'+Je(e)+'"]'}function Ra(e){return"script[async]"+e}function sd(e,a,o){if(a.count++,a.instance===null)switch(a.type){case"style":var f=e.querySelector('style[data-href~="'+Je(o.href)+'"]');if(f)return a.instance=f,Ae(f),f;var p=g({},o,{"data-href":o.href,"data-precedence":o.precedence,href:null,precedence:null});return f=(e.ownerDocument||e).createElement("style"),Ae(f),Se(f,"style",p),fl(f,o.precedence,e),a.instance=f;case"stylesheet":p=Ns(o.href);var x=e.querySelector(Ia(p));if(x)return a.state.loading|=4,a.instance=x,Ae(x),x;f=nd(o),(p=ri.get(p))&&lh(f,p),x=(e.ownerDocument||e).createElement("link"),Ae(x);var D=x;return D._p=new Promise(function(O,q){D.onload=O,D.onerror=q}),Se(x,"link",f),a.state.loading|=4,fl(x,o.precedence,e),a.instance=x;case"script":return x=Vs(o.src),(p=e.querySelector(Ra(x)))?(a.instance=p,Ae(p),p):(f=o,(p=ri.get(x))&&(f=g({},o),oh(f,p)),e=e.ownerDocument||e,p=e.createElement("script"),Ae(p),Se(p,"link",f),e.head.appendChild(p),a.instance=p);case"void":return null;default:throw Error(s(443,a.type))}else a.type==="stylesheet"&&(a.state.loading&4)===0&&(f=a.instance,a.state.loading|=4,fl(f,o.precedence,e));return a.instance}function fl(e,a,o){for(var f=o.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),p=f.length?f[f.length-1]:null,x=p,D=0;D title"):null)}function wA(e,a,o){if(o===1||a.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof a.precedence!="string"||typeof a.href!="string"||a.href==="")break;return!0;case"link":if(typeof a.rel!="string"||typeof a.href!="string"||a.href===""||a.onLoad||a.onError)break;switch(a.rel){case"stylesheet":return e=a.disabled,typeof a.precedence=="string"&&e==null;default:return!0}case"script":if(a.async&&typeof a.async!="function"&&typeof a.async!="symbol"&&!a.onLoad&&!a.onError&&a.src&&typeof a.src=="string")return!0}return!1}function ld(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function bA(e,a,o,f){if(o.type==="stylesheet"&&(typeof f.media!="string"||matchMedia(f.media).matches!==!1)&&(o.state.loading&4)===0){if(o.instance===null){var p=Ns(f.href),x=a.querySelector(Ia(p));if(x){a=x._p,a!==null&&typeof a=="object"&&typeof a.then=="function"&&(e.count++,e=ml.bind(e),a.then(e,e)),o.state.loading|=4,o.instance=x,Ae(x);return}x=a.ownerDocument||a,f=nd(f),(p=ri.get(p))&&lh(f,p),x=x.createElement("link"),Ae(x);var D=x;D._p=new Promise(function(O,q){D.onload=O,D.onerror=q}),Se(x,"link",f),o.instance=x}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(o,a),(a=o.state.preload)&&(o.state.loading&3)===0&&(e.count++,o=ml.bind(e),a.addEventListener("load",o),a.addEventListener("error",o))}}var ch=0;function CA(e,a){return e.stylesheets&&e.count===0&&Al(e,e.stylesheets),0ch?50:800)+a);return e.unsuspend=o,function(){e.unsuspend=null,clearTimeout(f),clearTimeout(p)}}:null}function ml(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Al(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var gl=null;function Al(e,a){e.stylesheets=null,e.unsuspend!==null&&(e.count++,gl=new Map,a.forEach(SA,e),gl=null,ml.call(e))}function SA(e,a){if(!(a.state.loading&4)){var o=gl.get(e);if(o)var f=o.get(null);else{o=new Map,gl.set(e,o);for(var p=e.querySelectorAll("link[data-precedence],style[data-precedence]"),x=0;x"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(t){console.error(t)}}return i(),vh.exports=YA(),vh.exports}var HA=GA();function qA({children:i}){return ht.jsxs("div",{className:"min-h-screen bg-gray-950 text-white",children:[ht.jsx("header",{className:"border-b border-gray-800 py-4",children:ht.jsxs("div",{className:"container mx-auto px-4",children:[ht.jsx("h1",{className:"text-2xl font-bold",children:"Stroke Lesion Segmentation"}),ht.jsx("p",{className:"text-gray-400 text-sm mt-1",children:"DeepISLES segmentation on ISLES24 dataset"})]})}),ht.jsx("main",{className:"container mx-auto px-4 py-6",children:i})]})}async function bh(i){try{return await i.json()}catch{return{}}}function XA(){return"https://vibecodermcswaggins-stroke-deepisles-demo.hf.space"}const KA=XA();class Kn extends Error{status;detail;constructor(t,n,s){super(t),this.name="ApiError",this.status=n,this.detail=s}}class jA{baseUrl;constructor(t){this.baseUrl=t}async getCases(t){const n=await fetch(`${this.baseUrl}/api/cases`,{signal:t});if(!n.ok){const s=await bh(n);throw new Kn(`Failed to fetch cases: ${n.statusText}`,n.status,s.detail)}return n.json()}async createSegmentJob(t,n=!0,s){const r=await fetch(`${this.baseUrl}/api/segment`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({case_id:t,fast_mode:n}),signal:s});if(!r.ok){const c=await bh(r);throw new Kn(`Failed to create job: ${c.detail||r.statusText}`,r.status,c.detail)}return r.json()}async getJobStatus(t,n){const s=await fetch(`${this.baseUrl}/api/jobs/${t}`,{signal:n});if(s.status===404)throw new Kn("Job not found or expired",404,"Jobs expire after 1 hour");if(!s.ok){const r=await bh(s);throw new Kn(`Failed to get job status: ${r.detail||s.statusText}`,s.status,r.detail)}return s.json()}}const Gh=new jA(KA),qs=5,QA=2e3,ZA=3e4;function w2(i){return Math.min(QA*Math.pow(2,i-1),ZA)}function WA(i){return new Promise(t=>setTimeout(t,i))}function _A({selectedCase:i,onSelectCase:t}){const[n,s]=Lt.useState([]),[r,c]=Lt.useState(!0),[l,d]=Lt.useState(null),[h,u]=Lt.useState(0),[m,g]=Lt.useState(!1);return Lt.useEffect(()=>{let A=!0;const v=new AbortController;async function y(){let w=0;for(;w<=qs&&A;)try{const b=await Gh.getCases(v.signal);if(!A)return;s(b.cases),g(!1),u(0),c(!1);return}catch(b){if(!A||b instanceof Error&&b.name==="AbortError")return;const C=b instanceof Kn&&b.status===503,S=b instanceof TypeError&&b.message.toLowerCase().includes("fetch");if((C||S)&&wsetTimeout(M,w2(w)));continue}const E=C||S?"Backend failed to wake up. Please refresh the page.":b instanceof Error?b.message:"Unknown error";d(`Failed to load cases: ${E}`),g(!1),c(!1);return}}return y(),()=>{A=!1,v.abort()}},[]),r?ht.jsx("div",{className:"bg-gray-800 rounded-lg p-4",children:m?ht.jsxs("p",{className:"text-yellow-400",children:["Backend waking up... Retry ",h,"/",qs]}):ht.jsx("p",{className:"text-gray-400",children:"Loading cases..."})}):l?ht.jsx("div",{className:"bg-red-900/50 rounded-lg p-4",children:ht.jsx("p",{className:"text-red-300",children:l})}):ht.jsxs("div",{className:"bg-gray-800 rounded-lg p-4",children:[ht.jsx("label",{className:"block text-sm font-medium mb-2",children:"Select Case"}),ht.jsxs("select",{value:i||"",onChange:A=>t(A.target.value),className:`w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 + text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent`,children:[ht.jsx("option",{value:"",children:"Choose a case..."}),n.map(A=>ht.jsx("option",{value:A,children:A},A))]})]})}var JA=1e-6,xe=typeof Float32Array<"u"?Float32Array:Array;function Hh(){var i=new xe(9);return xe!=Float32Array&&(i[1]=0,i[2]=0,i[3]=0,i[5]=0,i[6]=0,i[7]=0),i[0]=1,i[4]=1,i[8]=1,i}function $A(i,t){return i[0]=t[0],i[1]=t[1],i[2]=t[2],i[3]=t[4],i[4]=t[5],i[5]=t[6],i[6]=t[8],i[7]=t[9],i[8]=t[10],i}function vn(i,t,n,s,r,c,l,d,h){var u=new xe(9);return u[0]=i,u[1]=t,u[2]=n,u[3]=s,u[4]=r,u[5]=c,u[6]=l,u[7]=d,u[8]=h,u}function tp(i,t){var n=t[0],s=t[1],r=t[2],c=t[3],l=t[4],d=t[5],h=t[6],u=t[7],m=t[8],g=m*l-d*u,A=-m*c+d*h,v=u*c-l*h,y=n*g+s*A+r*v;return y?(y=1/y,i[0]=g*y,i[1]=(-m*s+r*u)*y,i[2]=(d*s-r*l)*y,i[3]=A*y,i[4]=(m*n-r*h)*y,i[5]=(-d*n+r*c)*y,i[6]=v*y,i[7]=(-u*n+s*h)*y,i[8]=(l*n-s*c)*y,i):null}function b2(i,t,n){var s=t[0],r=t[1],c=t[2],l=t[3],d=t[4],h=t[5],u=t[6],m=t[7],g=t[8],A=n[0],v=n[1],y=n[2],w=n[3],b=n[4],C=n[5],S=n[6],E=n[7],M=n[8];return i[0]=A*s+v*l+y*u,i[1]=A*r+v*d+y*m,i[2]=A*c+v*h+y*g,i[3]=w*s+b*l+C*u,i[4]=w*r+b*d+C*m,i[5]=w*c+b*h+C*g,i[6]=S*s+E*l+M*u,i[7]=S*r+E*d+M*m,i[8]=S*c+E*h+M*g,i}function Ut(){var i=new xe(16);return xe!=Float32Array&&(i[1]=0,i[2]=0,i[3]=0,i[4]=0,i[6]=0,i[7]=0,i[8]=0,i[9]=0,i[11]=0,i[12]=0,i[13]=0,i[14]=0),i[0]=1,i[5]=1,i[10]=1,i[15]=1,i}function re(i){var t=new xe(16);return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],t[9]=i[9],t[10]=i[10],t[11]=i[11],t[12]=i[12],t[13]=i[13],t[14]=i[14],t[15]=i[15],t}function ep(i,t){return i[0]=t[0],i[1]=t[1],i[2]=t[2],i[3]=t[3],i[4]=t[4],i[5]=t[5],i[6]=t[6],i[7]=t[7],i[8]=t[8],i[9]=t[9],i[10]=t[10],i[11]=t[11],i[12]=t[12],i[13]=t[13],i[14]=t[14],i[15]=t[15],i}function oi(i,t,n,s,r,c,l,d,h,u,m,g,A,v,y,w){var b=new xe(16);return b[0]=i,b[1]=t,b[2]=n,b[3]=s,b[4]=r,b[5]=c,b[6]=l,b[7]=d,b[8]=h,b[9]=u,b[10]=m,b[11]=g,b[12]=A,b[13]=v,b[14]=y,b[15]=w,b}function C2(i){return i[0]=1,i[1]=0,i[2]=0,i[3]=0,i[4]=0,i[5]=1,i[6]=0,i[7]=0,i[8]=0,i[9]=0,i[10]=1,i[11]=0,i[12]=0,i[13]=0,i[14]=0,i[15]=1,i}function We(i,t){if(i===t){var n=t[1],s=t[2],r=t[3],c=t[6],l=t[7],d=t[11];i[1]=t[4],i[2]=t[8],i[3]=t[12],i[4]=n,i[6]=t[9],i[7]=t[13],i[8]=s,i[9]=c,i[11]=t[14],i[12]=r,i[13]=l,i[14]=d}else i[0]=t[0],i[1]=t[4],i[2]=t[8],i[3]=t[12],i[4]=t[1],i[5]=t[5],i[6]=t[9],i[7]=t[13],i[8]=t[2],i[9]=t[6],i[10]=t[10],i[11]=t[14],i[12]=t[3],i[13]=t[7],i[14]=t[11],i[15]=t[15];return i}function Pe(i,t){var n=t[0],s=t[1],r=t[2],c=t[3],l=t[4],d=t[5],h=t[6],u=t[7],m=t[8],g=t[9],A=t[10],v=t[11],y=t[12],w=t[13],b=t[14],C=t[15],S=n*d-s*l,E=n*h-r*l,M=n*u-c*l,N=s*h-r*d,U=s*u-c*d,T=r*u-c*h,F=m*w-g*y,I=m*b-A*y,B=m*C-v*y,V=g*b-A*w,R=g*C-v*w,Y=A*C-v*b,P=S*Y-E*R+M*V+N*B-U*I+T*F;return P?(P=1/P,i[0]=(d*Y-h*R+u*V)*P,i[1]=(r*R-s*Y-c*V)*P,i[2]=(w*T-b*U+C*N)*P,i[3]=(A*U-g*T-v*N)*P,i[4]=(h*B-l*Y-u*I)*P,i[5]=(n*Y-r*B+c*I)*P,i[6]=(b*M-y*T-C*E)*P,i[7]=(m*T-A*M+v*E)*P,i[8]=(l*R-d*B+u*F)*P,i[9]=(s*B-n*R-c*F)*P,i[10]=(y*U-w*M+C*S)*P,i[11]=(g*M-m*U-v*S)*P,i[12]=(d*I-l*V-h*F)*P,i[13]=(n*V-s*I+r*F)*P,i[14]=(w*E-y*N-b*S)*P,i[15]=(m*N-g*E+A*S)*P,i):null}function qn(i,t,n){var s=t[0],r=t[1],c=t[2],l=t[3],d=t[4],h=t[5],u=t[6],m=t[7],g=t[8],A=t[9],v=t[10],y=t[11],w=t[12],b=t[13],C=t[14],S=t[15],E=n[0],M=n[1],N=n[2],U=n[3];return i[0]=E*s+M*d+N*g+U*w,i[1]=E*r+M*h+N*A+U*b,i[2]=E*c+M*u+N*v+U*C,i[3]=E*l+M*m+N*y+U*S,E=n[4],M=n[5],N=n[6],U=n[7],i[4]=E*s+M*d+N*g+U*w,i[5]=E*r+M*h+N*A+U*b,i[6]=E*c+M*u+N*v+U*C,i[7]=E*l+M*m+N*y+U*S,E=n[8],M=n[9],N=n[10],U=n[11],i[8]=E*s+M*d+N*g+U*w,i[9]=E*r+M*h+N*A+U*b,i[10]=E*c+M*u+N*v+U*C,i[11]=E*l+M*m+N*y+U*S,E=n[12],M=n[13],N=n[14],U=n[15],i[12]=E*s+M*d+N*g+U*w,i[13]=E*r+M*h+N*A+U*b,i[14]=E*c+M*u+N*v+U*C,i[15]=E*l+M*m+N*y+U*S,i}function Ps(i,t,n){var s=n[0],r=n[1],c=n[2],l,d,h,u,m,g,A,v,y,w,b,C;return t===i?(i[12]=t[0]*s+t[4]*r+t[8]*c+t[12],i[13]=t[1]*s+t[5]*r+t[9]*c+t[13],i[14]=t[2]*s+t[6]*r+t[10]*c+t[14],i[15]=t[3]*s+t[7]*r+t[11]*c+t[15]):(l=t[0],d=t[1],h=t[2],u=t[3],m=t[4],g=t[5],A=t[6],v=t[7],y=t[8],w=t[9],b=t[10],C=t[11],i[0]=l,i[1]=d,i[2]=h,i[3]=u,i[4]=m,i[5]=g,i[6]=A,i[7]=v,i[8]=y,i[9]=w,i[10]=b,i[11]=C,i[12]=l*s+m*r+y*c+t[12],i[13]=d*s+g*r+w*c+t[13],i[14]=h*s+A*r+b*c+t[14],i[15]=u*s+v*r+C*c+t[15]),i}function Bd(i,t,n){var s=n[0],r=n[1],c=n[2];return i[0]=t[0]*s,i[1]=t[1]*s,i[2]=t[2]*s,i[3]=t[3]*s,i[4]=t[4]*r,i[5]=t[5]*r,i[6]=t[6]*r,i[7]=t[7]*r,i[8]=t[8]*c,i[9]=t[9]*c,i[10]=t[10]*c,i[11]=t[11]*c,i[12]=t[12],i[13]=t[13],i[14]=t[14],i[15]=t[15],i}function Sl(i,t,n){var s=Math.sin(n),r=Math.cos(n),c=t[4],l=t[5],d=t[6],h=t[7],u=t[8],m=t[9],g=t[10],A=t[11];return t!==i&&(i[0]=t[0],i[1]=t[1],i[2]=t[2],i[3]=t[3],i[12]=t[12],i[13]=t[13],i[14]=t[14],i[15]=t[15]),i[4]=c*r+u*s,i[5]=l*r+m*s,i[6]=d*r+g*s,i[7]=h*r+A*s,i[8]=u*r-c*s,i[9]=m*r-l*s,i[10]=g*r-d*s,i[11]=A*r-h*s,i}function Ml(i,t,n){var s=Math.sin(n),r=Math.cos(n),c=t[0],l=t[1],d=t[2],h=t[3],u=t[4],m=t[5],g=t[6],A=t[7];return t!==i&&(i[8]=t[8],i[9]=t[9],i[10]=t[10],i[11]=t[11],i[12]=t[12],i[13]=t[13],i[14]=t[14],i[15]=t[15]),i[0]=c*r+u*s,i[1]=l*r+m*s,i[2]=d*r+g*s,i[3]=h*r+A*s,i[4]=u*r-c*s,i[5]=m*r-l*s,i[6]=g*r-d*s,i[7]=A*r-h*s,i}function ip(i,t,n){var s=n[0],r=n[1],c=n[2],l=Math.sqrt(s*s+r*r+c*c),d,h,u;return l0&&(c=1/Math.sqrt(c)),i[0]=t[0]*c,i[1]=t[1]*c,i[2]=t[2]*c,i}function op(i,t){return i[0]*t[0]+i[1]*t[1]+i[2]*t[2]}function Ll(i,t,n){var s=t[0],r=t[1],c=t[2],l=n[0],d=n[1],h=n[2];return i[0]=r*h-c*d,i[1]=c*l-s*h,i[2]=s*d-r*l,i}function cp(i,t,n,s){var r=t[0],c=t[1],l=t[2];return i[0]=r+s*(n[0]-r),i[1]=c+s*(n[1]-c),i[2]=l+s*(n[2]-l),i}function Rd(i,t,n){var s=t[0],r=t[1],c=t[2];return i[0]=s*n[0]+r*n[3]+c*n[6],i[1]=s*n[1]+r*n[4]+c*n[7],i[2]=s*n[2]+r*n[5]+c*n[8],i}function Ch(i,t){var n=i[0],s=i[1],r=i[2],c=t[0],l=t[1],d=t[2],h=Math.sqrt((n*n+s*s+r*r)*(c*c+l*l+d*d)),u=h&&op(i,t)/h;return Math.acos(Math.min(Math.max(u,-1),1))}var Nd=jt,tr=wn;(function(){var i=Gt();return function(t,n,s,r,c,l){var d,h;for(n||(n=3),s||(s=0),r?h=Math.min(r*n+s,t.length):h=t.length,d=s;d0&&(r=1/Math.sqrt(r)),i[0]=t[0]*r,i[1]=t[1]*r,i}(function(){var i=dp();return function(t,n,s,r,c,l){var d,h;for(n||(n=2),s||(s=0),r?h=Math.min(r*n+s,t.length):h=t.length,d=s;d256){for(Dl=Array(i=256);i--;)Dl[i]=256*Math.random()|0;i=jn=0}for(;i<16;i++)t=Dl[jn+i],i==6?n+=Ol[t&15|64]:i==8?n+=Ol[t&63|128]:n+=Ol[t],i&1&&i>1&&i<11&&(n+="-");return jn++,n}var Sh,zd;function Ap(){return zd||(zd=1,Sh=function(t,n){var s=t.length;if(t===n)return!0;if(s!==n.length)return!1;for(var r=0;r{const n=(r,c)=>(i.set(c,r),r),s=r=>{if(i.has(r))return i.get(r);const[c,l]=t[r];switch(c){case jl:case M2:return n(l,r);case Wa:{const d=n([],r);for(const h of l)d.push(s(h));return d}case ql:{const d=n({},r);for(const[h,u]of l)d[s(h)]=s(u);return d}case tu:return n(new Date(l),r);case eu:{const{source:d,flags:h}=l;return n(new RegExp(d,h),r)}case iu:{const d=n(new Map,r);for(const[h,u]of l)d.set(s(h),s(u));return d}case nu:{const d=n(new Set,r);for(const h of l)d.add(s(h));return d}case E2:{const{name:d,message:h}=l;return n(new Pd[d](h),r)}case D2:return n(BigInt(l),r);case"BigInt":return n(Object(BigInt(l)),r);case"ArrayBuffer":return n(new Uint8Array(l).buffer,l);case"DataView":{const{buffer:d}=new Uint8Array(l);return n(new DataView(d),l)}}return n(new Pd[c](l),r)};return s},yp=i=>xp(new Map,i)(0),Os="",{toString:wp}={},{keys:bp}=Object,ka=i=>{const t=typeof i;if(t!=="object"||!i)return[jl,t];const n=wp.call(i).slice(8,-1);switch(n){case"Array":return[Wa,Os];case"Object":return[ql,Os];case"Date":return[tu,Os];case"RegExp":return[eu,Os];case"Map":return[iu,Os];case"Set":return[nu,Os];case"DataView":return[Wa,n]}return n.includes("Array")?[Wa,n]:n.includes("Error")?[E2,n]:[ql,n]},Tl=([i,t])=>i===jl&&(t==="function"||t==="symbol"),Cp=(i,t,n,s)=>{const r=(l,d)=>{const h=s.push(l)-1;return n.set(d,h),h},c=l=>{if(n.has(l))return n.get(l);let[d,h]=ka(l);switch(d){case jl:{let m=l;switch(h){case"bigint":d=D2,m=l.toString();break;case"function":case"symbol":if(i)throw new TypeError("unable to serialize "+h);m=null;break;case"undefined":return r([M2],l)}return r([d,m],l)}case Wa:{if(h){let A=l;return h==="DataView"?A=new Uint8Array(l.buffer):h==="ArrayBuffer"&&(A=new Uint8Array(l)),r([h,[...A]],l)}const m=[],g=r([d,m],l);for(const A of l)m.push(c(A));return g}case ql:{if(h)switch(h){case"BigInt":return r([h,l.toString()],l);case"Boolean":case"Number":case"String":return r([h,l.valueOf()],l)}if(t&&"toJSON"in l)return c(l.toJSON());const m=[],g=r([d,m],l);for(const A of bp(l))(i||!Tl(ka(l[A])))&&m.push([c(A),c(l[A])]);return g}case tu:return r([d,l.toISOString()],l);case eu:{const{source:m,flags:g}=l;return r([d,{source:m,flags:g}],l)}case iu:{const m=[],g=r([d,m],l);for(const[A,v]of l)(i||!(Tl(ka(A))||Tl(ka(v))))&&m.push([c(A),c(v)]);return g}case nu:{const m=[],g=r([d,m],l);for(const A of l)(i||!Tl(ka(A)))&&m.push(c(A));return g}}const{message:u}=l;return r([d,{name:h,message:u}],l)};return c},Sp=(i,{json:t,lossy:n}={})=>{const s=[];return Cp(!(t||n),!!t,new Map,s)(i),s};var ve=Uint8Array,Hs=Uint16Array,Mp=Int32Array,T2=new ve([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),U2=new ve([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),Ep=new ve([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),F2=function(i,t){for(var n=new Hs(31),s=0;s<31;++s)n[s]=t+=1<>1|(Wt&21845)<<1;dn=(dn&52428)>>2|(dn&13107)<<2,dn=(dn&61680)>>4|(dn&3855)<<4,Xh[Wt]=((dn&65280)>>8|(dn&255)<<8)>>1}var _a=(function(i,t,n){for(var s=i.length,r=0,c=new Hs(t);r>h]=u}else for(d=new Hs(s),r=0;r>15-i[r]);return d}),er=new ve(288);for(var Wt=0;Wt<144;++Wt)er[Wt]=8;for(var Wt=144;Wt<256;++Wt)er[Wt]=9;for(var Wt=256;Wt<280;++Wt)er[Wt]=7;for(var Wt=280;Wt<288;++Wt)er[Wt]=8;var R2=new ve(32);for(var Wt=0;Wt<32;++Wt)R2[Wt]=5;var Fp=_a(er,9,1),Bp=_a(R2,5,1),Mh=function(i){for(var t=i[0],n=1;nt&&(t=i[n]);return t},fi=function(i,t,n){var s=t/8|0;return(i[s]|i[s+1]<<8)>>(t&7)&n},Eh=function(i,t){var n=t/8|0;return(i[n]|i[n+1]<<8|i[n+2]<<16)>>(t&7)},N2=function(i){return(i+7)/8|0},zl=function(i,t,n){return(t==null||t<0)&&(t=0),(n==null||n>i.length)&&(n=i.length),new ve(i.subarray(t,n))},Ip=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],Fe=function(i,t,n){var s=new Error(t||Ip[i]);if(s.code=i,Error.captureStackTrace&&Error.captureStackTrace(s,Fe),!n)throw s;return s},Ql=function(i,t,n,s){var r=i.length,c=0;if(!r||t.f&&!t.l)return n||new ve(0);var l=!n,d=l||t.i!=2,h=t.i;l&&(n=new ve(r*3));var u=function(ue){var fe=n.length;if(ue>fe){var Jn=new ve(Math.max(fe*2,ue));Jn.set(n),n=Jn}},m=t.f||0,g=t.p||0,A=t.b||0,v=t.l,y=t.d,w=t.m,b=t.n,C=r*8;do{if(!v){m=fi(i,g,1);var S=fi(i,g+1,3);if(g+=3,S)if(S==1)v=Fp,y=Bp,w=9,b=5;else if(S==2){var U=fi(i,g,31)+257,T=fi(i,g+10,15)+4,F=U+fi(i,g+5,31)+1;g+=14;for(var I=new ve(F),B=new ve(19),V=0;V>4;if(E<16)I[V++]=E;else{var L=0,H=0;for(E==16?(H=3+fi(i,g,3),g+=2,L=I[V-1]):E==17?(H=3+fi(i,g,7),g+=3):E==18&&(H=11+fi(i,g,127),g+=7);H--;)I[V++]=L}}var W=I.subarray(0,U),at=I.subarray(U);w=Mh(W),b=Mh(at),v=_a(W,w,1),y=_a(at,b,1)}else Fe(1);else{var E=N2(g)+4,M=i[E-4]|i[E-3]<<8,N=E+M;if(N>r){h&&Fe(0);break}d&&u(A+M),n.set(i.subarray(E,N),A),t.b=A+=M,t.p=g=N*8,t.f=m;continue}if(g>C){h&&Fe(0);break}}d&&u(A+131072);for(var ct=(1<>4;if(g+=L&15,g>C){h&&Fe(0);break}if(L||Fe(2),$<256)n[A++]=$;else if($==256){j=g,v=null;break}else{var et=$-254;if($>264){var V=$-257,ot=T2[V];et=fi(i,g,(1<>4;mt||Fe(3),g+=mt&15;var at=Up[vt];if(vt>3){var ot=U2[vt];at+=Eh(i,g)&(1<C){h&&Fe(0);break}d&&u(A+131072);var Rt=A+et;if(A>3&1)+(t>>4&1);s>0;s-=!i[n++]);return n+(t&2)},Np=function(i){var t=i.length;return(i[t-4]|i[t-3]<<8|i[t-2]<<16|i[t-1]<<24)>>>0},Vp=function(i,t){return((i[0]&15)!=8||i[0]>>4>7||(i[0]<<8|i[1])%31)&&Fe(6,"invalid zlib data"),(i[1]>>5&1)==1&&Fe(6,"invalid zlib data: "+(i[1]&32?"need":"unexpected")+" dictionary"),(i[1]>>3&4)+2},Dh=(function(){function i(t,n){typeof t=="function"&&(n=t,t={}),this.ondata=n;var s=t&&t.dictionary&&t.dictionary.subarray(-32768);this.s={i:0,b:s?s.length:0},this.o=new ve(32768),this.p=new ve(0),s&&this.o.set(s)}return i.prototype.e=function(t){if(this.ondata||Fe(5),this.d&&Fe(4),!this.p.length)this.p=t;else if(t.length){var n=new ve(this.p.length+t.length);n.set(this.p),n.set(t,this.p.length),this.p=n}},i.prototype.c=function(t){this.s.i=+(this.d=t||!1);var n=this.s.b,s=Ql(this.p,this.s,this.o);this.ondata(zl(s,n,this.s.b),this.d),this.o=zl(s,this.s.b-32768),this.s.b=this.o.length,this.p=zl(this.p,this.s.p/8|0),this.s.p&=7},i.prototype.push=function(t,n){this.e(t),this.c(n)},i})();function Lp(i,t){return Ql(i,{i:2},t,t)}var Op=(function(){function i(t,n){this.v=1,this.r=0,Dh.call(this,t,n)}return i.prototype.push=function(t,n){if(Dh.prototype.e.call(this,t),this.r+=t.length,this.v){var s=this.p.subarray(this.v-1),r=s.length>3?V2(s):4;if(r>s.length){if(!n)return}else this.v>1&&this.onmember&&this.onmember(this.r-s.length);this.p=s.subarray(r),this.v=0}Dh.prototype.c.call(this,n),this.s.f&&!this.s.l&&!n&&(this.v=N2(this.s.p)+9,this.s={i:0},this.o=new ve(0),this.push(new ve(0),n))},i})();function zp(i,t){var n=V2(i);return n+8>i.length&&Fe(6,"invalid gzip data"),Ql(i.subarray(n,-8),{i:2},new ve(Np(i)),t)}function Pp(i,t){return Ql(i.subarray(Vp(i),-4),{i:2},t,t)}function kp(i,t){return i[0]==31&&i[1]==139&&i[2]==8?zp(i,t):(i[0]&15)!=8||i[0]>>4>7||(i[0]<<8|i[1])%31?Lp(i,t):Pp(i,t)}var Yp=typeof TextDecoder<"u"&&new TextDecoder,Gp=0;try{Yp.decode(Rp,{stream:!0}),Gp=1}catch{}class L2{esize;ecode;edata;littleEndian;constructor(t,n,s,r){if(t%16!=0)throw new Error("This does not appear to be a NIFTI extension");this.esize=t,this.ecode=n,this.edata=s,this.littleEndian=r}toArrayBuffer(){let t=new Uint8Array(this.esize),n=new Uint8Array(this.edata);t.set(n,8);let s=new DataView(t.buffer);return s.setInt32(0,this.esize,this.littleEndian),s.setInt32(4,this.ecode,this.littleEndian),t.buffer}}class rt{static crcTable=null;static GUNZIP_MAGIC_COOKIE1=31;static GUNZIP_MAGIC_COOKIE2=139;static getStringAt(t,n,s){var r="",c,l;for(c=n;cr&&(d=!d,h=rt.getIntAt(t,l,d),h+l>r))throw new Error("This does not appear to be a valid NIFTI extension");if(h%16!=0)throw new Error("This does not appear to be a NIFTI extension");let u=rt.getIntAt(t,l+4,d),m=t.buffer.slice(l+8,l+h),g=new L2(h,u,m,d);c.push(g),l+=h}return c}static toArrayBuffer(t){var n,s,r;for(n=new ArrayBuffer(t.length),s=new Uint8Array(n),r=0;r>>1:t>>>1;n[s]=t}return n}static crc32(t){rt.crcTable||(rt.crcTable=rt.makeCRCTable());const n=rt.crcTable;let s=-1;for(var r=0;r>>8^n[(s^t.getUint8(r))&255];return(s^-1)>>>0}}class ut{littleEndian=!1;dim_info=0;dims=[];intent_p1=0;intent_p2=0;intent_p3=0;intent_code=0;datatypeCode=0;numBitsPerVoxel=0;slice_start=0;slice_end=0;slice_code=0;pixDims=[];vox_offset=0;scl_slope=1;scl_inter=0;xyzt_units=0;cal_max=0;cal_min=0;slice_duration=0;toffset=0;description="";aux_file="";intent_name="";qform_code=0;sform_code=0;quatern_a=0;quatern_b=0;quatern_c=0;quatern_d=0;qoffset_x=0;qoffset_y=0;qoffset_z=0;affine=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];qfac=1;quatern_R;magic="0";isHDR=!1;extensionFlag=[0,0,0,0];extensionSize=0;extensionCode=0;extensions=[];static TYPE_NONE=0;static TYPE_BINARY=1;static TYPE_UINT8=2;static TYPE_INT16=4;static TYPE_INT32=8;static TYPE_FLOAT32=16;static TYPE_COMPLEX64=32;static TYPE_FLOAT64=64;static TYPE_RGB24=128;static TYPE_INT8=256;static TYPE_UINT16=512;static TYPE_UINT32=768;static TYPE_INT64=1024;static TYPE_UINT64=1280;static TYPE_FLOAT128=1536;static TYPE_COMPLEX128=1792;static TYPE_COMPLEX256=2048;static XFORM_UNKNOWN=0;static XFORM_SCANNER_ANAT=1;static XFORM_ALIGNED_ANAT=2;static XFORM_TALAIRACH=3;static XFORM_MNI_152=4;static SPATIAL_UNITS_MASK=7;static TEMPORAL_UNITS_MASK=56;static UNITS_UNKNOWN=0;static UNITS_METER=1;static UNITS_MM=2;static UNITS_MICRON=3;static UNITS_SEC=8;static UNITS_MSEC=16;static UNITS_USEC=24;static UNITS_HZ=32;static UNITS_PPM=40;static UNITS_RADS=48;static MAGIC_COOKIE=348;static STANDARD_HEADER_SIZE=348;static MAGIC_NUMBER_LOCATION=344;static MAGIC_NUMBER=[110,43,49];static MAGIC_NUMBER2=[110,105,49];static EXTENSION_HEADER_SIZE=8;readHeader(t){var n=new DataView(t),s=rt.getIntAt(n,0,this.littleEndian),r,c,l,d;if(s!==ut.MAGIC_COOKIE&&(this.littleEndian=!0,s=rt.getIntAt(n,0,this.littleEndian)),s!==ut.MAGIC_COOKIE)throw new Error("This does not appear to be a NIFTI file!");for(this.dim_info=rt.getByteAt(n,39),r=0;r<8;r+=1)d=40+r*2,this.dims[r]=rt.getShortAt(n,d,this.littleEndian);for(this.intent_p1=rt.getFloatAt(n,56,this.littleEndian),this.intent_p2=rt.getFloatAt(n,60,this.littleEndian),this.intent_p3=rt.getFloatAt(n,64,this.littleEndian),this.intent_code=rt.getShortAt(n,68,this.littleEndian),this.datatypeCode=rt.getShortAt(n,70,this.littleEndian),this.numBitsPerVoxel=rt.getShortAt(n,72,this.littleEndian),this.slice_start=rt.getShortAt(n,74,this.littleEndian),r=0;r<8;r+=1)d=76+r*4,this.pixDims[r]=rt.getFloatAt(n,d,this.littleEndian);if(this.vox_offset=rt.getFloatAt(n,108,this.littleEndian),this.scl_slope=rt.getFloatAt(n,112,this.littleEndian),this.scl_inter=rt.getFloatAt(n,116,this.littleEndian),this.slice_end=rt.getShortAt(n,120,this.littleEndian),this.slice_code=rt.getByteAt(n,122),this.xyzt_units=rt.getByteAt(n,123),this.cal_max=rt.getFloatAt(n,124,this.littleEndian),this.cal_min=rt.getFloatAt(n,128,this.littleEndian),this.slice_duration=rt.getFloatAt(n,132,this.littleEndian),this.toffset=rt.getFloatAt(n,136,this.littleEndian),this.description=rt.getStringAt(n,148,228),this.aux_file=rt.getStringAt(n,228,252),this.qform_code=rt.getShortAt(n,252,this.littleEndian),this.sform_code=rt.getShortAt(n,254,this.littleEndian),this.quatern_b=rt.getFloatAt(n,256,this.littleEndian),this.quatern_c=rt.getFloatAt(n,260,this.littleEndian),this.quatern_d=rt.getFloatAt(n,264,this.littleEndian),this.quatern_a=Math.sqrt(1-(Math.pow(this.quatern_b,2)+Math.pow(this.quatern_c,2)+Math.pow(this.quatern_d,2))),this.qoffset_x=rt.getFloatAt(n,268,this.littleEndian),this.qoffset_y=rt.getFloatAt(n,272,this.littleEndian),this.qoffset_z=rt.getFloatAt(n,276,this.littleEndian),this.qform_code<1&&this.sform_code<1&&(this.affine[0][0]=this.pixDims[1],this.affine[1][1]=this.pixDims[2],this.affine[2][2]=this.pixDims[3]),this.qform_code>0&&this.sform_code0)for(c=0;c<3;c+=1)for(l=0;l<4;l+=1)d=280+(c*4+l)*4,this.affine[c][l]=rt.getFloatAt(n,d,this.littleEndian);if(this.affine[3][0]=0,this.affine[3][1]=0,this.affine[3][2]=0,this.affine[3][3]=1,this.intent_name=rt.getStringAt(n,328,344),this.magic=rt.getStringAt(n,344,348),this.isHDR=this.magic===String.fromCharCode.apply(null,ut.MAGIC_NUMBER2),n.byteLength>ut.MAGIC_COOKIE){this.extensionFlag[0]=rt.getByteAt(n,348),this.extensionFlag[1]=rt.getByteAt(n,349),this.extensionFlag[2]=rt.getByteAt(n,350),this.extensionFlag[3]=rt.getByteAt(n,351);let h=!0;!this.isHDR&&this.vox_offset<=352&&(h=!1),n.byteLength<=368&&(h=!1),h&&this.extensionFlag[0]&&(this.extensions=rt.getExtensionsAt(n,this.getExtensionLocation(),this.littleEndian,this.vox_offset),this.extensionSize=this.extensions[0].esize,this.extensionCode=this.extensions[0].ecode)}}toFormattedString(){var t=rt.formatNumber,n="";return n+="Dim Info = "+this.dim_info+` +`,n+="Image Dimensions (1-8): "+this.dims[0]+", "+this.dims[1]+", "+this.dims[2]+", "+this.dims[3]+", "+this.dims[4]+", "+this.dims[5]+", "+this.dims[6]+", "+this.dims[7]+` +`,n+="Intent Parameters (1-3): "+this.intent_p1+", "+this.intent_p2+", "+this.intent_p3+` +`,n+="Intent Code = "+this.intent_code+` +`,n+="Datatype = "+this.datatypeCode+" ("+this.getDatatypeCodeString(this.datatypeCode)+`) +`,n+="Bits Per Voxel = "+this.numBitsPerVoxel+` +`,n+="Slice Start = "+this.slice_start+` +`,n+="Voxel Dimensions (1-8): "+t(this.pixDims[0])+", "+t(this.pixDims[1])+", "+t(this.pixDims[2])+", "+t(this.pixDims[3])+", "+t(this.pixDims[4])+", "+t(this.pixDims[5])+", "+t(this.pixDims[6])+", "+t(this.pixDims[7])+` +`,n+="Image Offset = "+this.vox_offset+` +`,n+="Data Scale: Slope = "+t(this.scl_slope)+" Intercept = "+t(this.scl_inter)+` +`,n+="Slice End = "+this.slice_end+` +`,n+="Slice Code = "+this.slice_code+` +`,n+="Units Code = "+this.xyzt_units+" ("+this.getUnitsCodeString(ut.SPATIAL_UNITS_MASK&this.xyzt_units)+", "+this.getUnitsCodeString(ut.TEMPORAL_UNITS_MASK&this.xyzt_units)+`) +`,n+="Display Range: Max = "+t(this.cal_max)+" Min = "+t(this.cal_min)+` +`,n+="Slice Duration = "+this.slice_duration+` +`,n+="Time Axis Shift = "+this.toffset+` +`,n+='Description: "'+this.description+`" +`,n+='Auxiliary File: "'+this.aux_file+`" +`,n+="Q-Form Code = "+this.qform_code+" ("+this.getTransformCodeString(this.qform_code)+`) +`,n+="S-Form Code = "+this.sform_code+" ("+this.getTransformCodeString(this.sform_code)+`) +`,n+="Quaternion Parameters: b = "+t(this.quatern_b)+" c = "+t(this.quatern_c)+" d = "+t(this.quatern_d)+` +`,n+="Quaternion Offsets: x = "+this.qoffset_x+" y = "+this.qoffset_y+" z = "+this.qoffset_z+` +`,n+="S-Form Parameters X: "+t(this.affine[0][0])+", "+t(this.affine[0][1])+", "+t(this.affine[0][2])+", "+t(this.affine[0][3])+` +`,n+="S-Form Parameters Y: "+t(this.affine[1][0])+", "+t(this.affine[1][1])+", "+t(this.affine[1][2])+", "+t(this.affine[1][3])+` +`,n+="S-Form Parameters Z: "+t(this.affine[2][0])+", "+t(this.affine[2][1])+", "+t(this.affine[2][2])+", "+t(this.affine[2][3])+` +`,n+='Intent Name: "'+this.intent_name+`" +`,this.extensionFlag[0]&&(n+="Extension: Size = "+this.extensionSize+" Code = "+this.extensionCode+` +`),n}getDatatypeCodeString=function(t){return t===ut.TYPE_UINT8?"1-Byte Unsigned Integer":t===ut.TYPE_INT16?"2-Byte Signed Integer":t===ut.TYPE_INT32?"4-Byte Signed Integer":t===ut.TYPE_FLOAT32?"4-Byte Float":t===ut.TYPE_FLOAT64?"8-Byte Float":t===ut.TYPE_RGB24?"RGB":t===ut.TYPE_INT8?"1-Byte Signed Integer":t===ut.TYPE_UINT16?"2-Byte Unsigned Integer":t===ut.TYPE_UINT32?"4-Byte Unsigned Integer":t===ut.TYPE_INT64?"8-Byte Signed Integer":t===ut.TYPE_UINT64?"8-Byte Unsigned Integer":"Unknown"};getTransformCodeString=function(t){return t===ut.XFORM_SCANNER_ANAT?"Scanner":t===ut.XFORM_ALIGNED_ANAT?"Aligned":t===ut.XFORM_TALAIRACH?"Talairach":t===ut.XFORM_MNI_152?"MNI":"Unknown"};getUnitsCodeString=function(t){return t===ut.UNITS_METER?"Meters":t===ut.UNITS_MM?"Millimeters":t===ut.UNITS_MICRON?"Microns":t===ut.UNITS_SEC?"Seconds":t===ut.UNITS_MSEC?"Milliseconds":t===ut.UNITS_USEC?"Microseconds":t===ut.UNITS_HZ?"Hz":t===ut.UNITS_PPM?"PPM":t===ut.UNITS_RADS?"Rads":"Unknown"};getQformMat(){return this.convertNiftiQFormToNiftiSForm(this.quatern_b,this.quatern_c,this.quatern_d,this.qoffset_x,this.qoffset_y,this.qoffset_z,this.pixDims[1],this.pixDims[2],this.pixDims[3],this.pixDims[0])}convertNiftiQFormToNiftiSForm(t,n,s,r,c,l,d,h,u,m){var g=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],A,v=t,y=n,w=s,b,C,S;return g[3][0]=g[3][1]=g[3][2]=0,g[3][3]=1,A=1-(v*v+y*y+w*w),A<1e-7?(A=1/Math.sqrt(v*v+y*y+w*w),v*=A,y*=A,w*=A,A=0):A=Math.sqrt(A),b=d>0?d:1,C=h>0?h:1,S=u>0?u:1,m<0&&(S=-S),g[0][0]=(A*A+v*v-y*y-w*w)*b,g[0][1]=2*(v*y-A*w)*C,g[0][2]=2*(v*w+A*y)*S,g[1][0]=2*(v*y+A*w)*b,g[1][1]=(A*A+y*y-v*v-w*w)*C,g[1][2]=2*(y*w-A*v)*S,g[2][0]=2*(v*w-A*y)*b,g[2][1]=2*(y*w+A*v)*C,g[2][2]=(A*A+w*w-y*y-v*v)*S,g[0][3]=r,g[1][3]=c,g[2][3]=l,g}convertNiftiSFormToNEMA(t){var n,s,r,c,l,d,h,u,m,g,A,v,y,w,b,C,S,E,M,N,U,T,F,I,B,V,R,Y,P,X,L,H,W,at;if(b=0,R=[[0,0,0],[0,0,0],[0,0,0]],Y=[[0,0,0],[0,0,0],[0,0,0]],n=t[0][0],s=t[0][1],r=t[0][2],c=t[1][0],l=t[1][1],d=t[1][2],h=t[2][0],u=t[2][1],m=t[2][2],g=Math.sqrt(n*n+c*c+h*h),g===0||(n/=g,c/=g,h/=g,g=Math.sqrt(s*s+l*l+u*u),g===0))return null;if(s/=g,l/=g,u/=g,g=n*s+c*l+h*u,Math.abs(g)>1e-4){if(s-=g*n,l-=g*c,u-=g*h,g=Math.sqrt(s*s+l*l+u*u),g===0)return null;s/=g,l/=g,u/=g}if(g=Math.sqrt(r*r+d*d+m*m),g===0?(r=c*u-h*l,d=h*s-u*n,m=n*l-c*s):(r/=g,d/=g,m/=g),g=n*r+c*d+h*m,Math.abs(g)>1e-4){if(r-=g*n,d-=g*c,m-=g*h,g=Math.sqrt(r*r+d*d+m*m),g===0)return null;r/=g,d/=g,m/=g}if(g=s*r+l*d+u*m,Math.abs(g)>1e-4){if(r-=g*s,d-=g*l,m-=g*u,g=Math.sqrt(r*r+d*d+m*m),g===0)return null;r/=g,d/=g,m/=g}if(R[0][0]=n,R[0][1]=s,R[0][2]=r,R[1][0]=c,R[1][1]=l,R[1][2]=d,R[2][0]=h,R[2][1]=u,R[2][2]=m,A=this.nifti_mat33_determ(R),A===0)return null;for(V=-666,M=T=F=I=1,N=2,U=3,y=1;y<=3;y+=1)for(w=1;w<=3;w+=1)if(y!==w){for(b=1;b<=3;b+=1)if(!(y===b||w===b))for(Y[0][0]=Y[0][1]=Y[0][2]=Y[1][0]=Y[1][1]=Y[1][2]=Y[2][0]=Y[2][1]=Y[2][2]=0,C=-1;C<=1;C+=2)for(S=-1;S<=1;S+=2)for(E=-1;E<=1;E+=2)Y[0][y-1]=C,Y[1][w-1]=S,Y[2][b-1]=E,v=this.nifti_mat33_determ(Y),v*A>0&&(B=this.nifti_mat33_mul(Y,R),g=B[0][0]+B[1][1]+B[2][2],g>V&&(V=g,M=y,N=w,U=b,T=C,F=S,I=E))}switch(P=X=L=H=W=at="",M*T){case 1:P="X",H="+";break;case-1:P="X",H="-";break;case 2:P="Y",H="+";break;case-2:P="Y",H="-";break;case 3:P="Z",H="+";break;case-3:P="Z",H="-";break}switch(N*F){case 1:X="X",W="+";break;case-1:X="X",W="-";break;case 2:X="Y",W="+";break;case-2:X="Y",W="-";break;case 3:X="Z",W="+";break;case-3:X="Z",W="-";break}switch(U*I){case 1:L="X",at="+";break;case-1:L="X",at="-";break;case 2:L="Y",at="+";break;case-2:L="Y",at="-";break;case 3:L="Z",at="+";break;case-3:L="Z",at="-";break}return P+X+L+H+W+at}nifti_mat33_mul=function(t,n){var s=[[0,0,0],[0,0,0],[0,0,0]],r,c;for(r=0;r<3;r+=1)for(c=0;c<3;c+=1)s[r][c]=t[r][0]*n[0][c]+t[r][1]*n[1][c]+t[r][2]*n[2][c];return s};nifti_mat33_determ=function(t){var n,s,r,c,l,d,h,u,m;return n=t[0][0],s=t[0][1],r=t[0][2],c=t[1][0],l=t[1][1],d=t[1][2],h=t[2][0],u=t[2][1],m=t[2][2],n*l*m-n*u*d-c*s*m+c*u*r+h*s*d-h*l*r};getExtensionLocation(){return ut.MAGIC_COOKIE+4}getExtensionSize(t){return rt.getIntAt(t,this.getExtensionLocation(),this.littleEndian)}getExtensionCode(t){return rt.getIntAt(t,this.getExtensionLocation()+4,this.littleEndian)}addExtension(t,n=-1){n==-1?this.extensions.push(t):this.extensions.splice(n,0,t),this.vox_offset+=t.esize}removeExtension(t){let n=this.extensions[t];n&&(this.vox_offset-=n.esize),this.extensions.splice(t,1)}toArrayBuffer(t=!1){let r=352;if(t)for(let h of this.extensions)r+=h.esize;let c=new Uint8Array(r),l=new DataView(c.buffer);l.setInt32(0,348,this.littleEndian),l.setUint8(39,this.dim_info);for(let h=0;h<8;h++)l.setUint16(40+2*h,this.dims[h],this.littleEndian);l.setFloat32(56,this.intent_p1,this.littleEndian),l.setFloat32(60,this.intent_p2,this.littleEndian),l.setFloat32(64,this.intent_p3,this.littleEndian),l.setInt16(68,this.intent_code,this.littleEndian),l.setInt16(70,this.datatypeCode,this.littleEndian),l.setInt16(72,this.numBitsPerVoxel,this.littleEndian),l.setInt16(74,this.slice_start,this.littleEndian);for(let h=0;h<8;h++)l.setFloat32(76+4*h,this.pixDims[h],this.littleEndian);l.setFloat32(108,this.vox_offset,this.littleEndian),l.setFloat32(112,this.scl_slope,this.littleEndian),l.setFloat32(116,this.scl_inter,this.littleEndian),l.setInt16(120,this.slice_end,this.littleEndian),l.setUint8(122,this.slice_code),l.setUint8(123,this.xyzt_units),l.setFloat32(124,this.cal_max,this.littleEndian),l.setFloat32(128,this.cal_min,this.littleEndian),l.setFloat32(132,this.slice_duration,this.littleEndian),l.setFloat32(136,this.toffset,this.littleEndian),c.set(new TextEncoder().encode(this.description),148),c.set(new TextEncoder().encode(this.aux_file),228),l.setInt16(252,this.qform_code,this.littleEndian),l.setInt16(254,this.sform_code,this.littleEndian),l.setFloat32(256,this.quatern_b,this.littleEndian),l.setFloat32(260,this.quatern_c,this.littleEndian),l.setFloat32(264,this.quatern_d,this.littleEndian),l.setFloat32(268,this.qoffset_x,this.littleEndian),l.setFloat32(272,this.qoffset_y,this.littleEndian),l.setFloat32(276,this.qoffset_z,this.littleEndian);const d=this.affine.flat();for(let h=0;h<12;h++)l.setFloat32(280+4*h,d[h],this.littleEndian);if(c.set(new TextEncoder().encode(this.intent_name),328),c.set(new TextEncoder().encode(this.magic),344),t){c.set(Uint8Array.from([1,0,0,0]),348);let h=this.getExtensionLocation();for(const u of this.extensions)l.setInt32(h,u.esize,u.littleEndian),l.setInt32(h+4,u.ecode,u.littleEndian),c.set(new Uint8Array(u.edata),h+8),h+=u.esize}else c.set(new Uint8Array(4).fill(0),348);return c.buffer}}class Me{littleEndian=!1;dim_info=0;dims=[];intent_p1=0;intent_p2=0;intent_p3=0;intent_code=0;datatypeCode=0;numBitsPerVoxel=0;slice_start=0;slice_end=0;slice_code=0;pixDims=[];vox_offset=0;scl_slope=1;scl_inter=0;xyzt_units=0;cal_max=0;cal_min=0;slice_duration=0;toffset=0;description="";aux_file="";intent_name="";qform_code=0;sform_code=0;quatern_b=0;quatern_c=0;quatern_d=0;qoffset_x=0;qoffset_y=0;qoffset_z=0;affine=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];magic="0";extensionFlag=[0,0,0,0];extensions=[];extensionSize=0;extensionCode=0;static MAGIC_COOKIE=540;static MAGIC_NUMBER_LOCATION=4;static MAGIC_NUMBER=[110,43,50,0,13,10,26,10];static MAGIC_NUMBER2=[110,105,50,0,13,10,26,10];readHeader(t){var n=new DataView(t),s=rt.getIntAt(n,0,this.littleEndian),r,c,l,d;if(s!==Me.MAGIC_COOKIE&&(this.littleEndian=!0,s=rt.getIntAt(n,0,this.littleEndian)),s!==Me.MAGIC_COOKIE)throw new Error("This does not appear to be a NIFTI file!");for(this.magic=rt.getStringAt(n,4,12),this.datatypeCode=rt.getShortAt(n,12,this.littleEndian),this.numBitsPerVoxel=rt.getShortAt(n,14,this.littleEndian),r=0;r<8;r+=1)d=16+r*8,this.dims[r]=rt.getInt64At(n,d,this.littleEndian);for(this.intent_p1=rt.getDoubleAt(n,80,this.littleEndian),this.intent_p2=rt.getDoubleAt(n,88,this.littleEndian),this.intent_p3=rt.getDoubleAt(n,96,this.littleEndian),r=0;r<8;r+=1)d=104+r*8,this.pixDims[r]=rt.getDoubleAt(n,d,this.littleEndian);for(this.vox_offset=rt.getInt64At(n,168,this.littleEndian),this.scl_slope=rt.getDoubleAt(n,176,this.littleEndian),this.scl_inter=rt.getDoubleAt(n,184,this.littleEndian),this.cal_max=rt.getDoubleAt(n,192,this.littleEndian),this.cal_min=rt.getDoubleAt(n,200,this.littleEndian),this.slice_duration=rt.getDoubleAt(n,208,this.littleEndian),this.toffset=rt.getDoubleAt(n,216,this.littleEndian),this.slice_start=rt.getInt64At(n,224,this.littleEndian),this.slice_end=rt.getInt64At(n,232,this.littleEndian),this.description=rt.getStringAt(n,240,320),this.aux_file=rt.getStringAt(n,320,344),this.qform_code=rt.getIntAt(n,344,this.littleEndian),this.sform_code=rt.getIntAt(n,348,this.littleEndian),this.quatern_b=rt.getDoubleAt(n,352,this.littleEndian),this.quatern_c=rt.getDoubleAt(n,360,this.littleEndian),this.quatern_d=rt.getDoubleAt(n,368,this.littleEndian),this.qoffset_x=rt.getDoubleAt(n,376,this.littleEndian),this.qoffset_y=rt.getDoubleAt(n,384,this.littleEndian),this.qoffset_z=rt.getDoubleAt(n,392,this.littleEndian),c=0;c<3;c+=1)for(l=0;l<4;l+=1)d=400+(c*4+l)*8,this.affine[c][l]=rt.getDoubleAt(n,d,this.littleEndian);this.affine[3][0]=0,this.affine[3][1]=0,this.affine[3][2]=0,this.affine[3][3]=1,this.slice_code=rt.getIntAt(n,496,this.littleEndian),this.xyzt_units=rt.getIntAt(n,500,this.littleEndian),this.intent_code=rt.getIntAt(n,504,this.littleEndian),this.intent_name=rt.getStringAt(n,508,524),this.dim_info=rt.getByteAt(n,524),n.byteLength>Me.MAGIC_COOKIE&&(this.extensionFlag[0]=rt.getByteAt(n,540),this.extensionFlag[1]=rt.getByteAt(n,541),this.extensionFlag[2]=rt.getByteAt(n,542),this.extensionFlag[3]=rt.getByteAt(n,543),this.extensionFlag[0]&&(this.extensions=rt.getExtensionsAt(n,this.getExtensionLocation(),this.littleEndian,this.vox_offset),this.extensionSize=this.extensions[0].esize,this.extensionCode=this.extensions[0].ecode))}toFormattedString(){var t=rt.formatNumber,n="";return n+="Datatype = "+ +this.datatypeCode+" ("+this.getDatatypeCodeString(this.datatypeCode)+`) +`,n+="Bits Per Voxel = = "+this.numBitsPerVoxel+` +`,n+="Image Dimensions (1-8): "+this.dims[0]+", "+this.dims[1]+", "+this.dims[2]+", "+this.dims[3]+", "+this.dims[4]+", "+this.dims[5]+", "+this.dims[6]+", "+this.dims[7]+` +`,n+="Intent Parameters (1-3): "+this.intent_p1+", "+this.intent_p2+", "+this.intent_p3+` +`,n+="Voxel Dimensions (1-8): "+t(this.pixDims[0])+", "+t(this.pixDims[1])+", "+t(this.pixDims[2])+", "+t(this.pixDims[3])+", "+t(this.pixDims[4])+", "+t(this.pixDims[5])+", "+t(this.pixDims[6])+", "+t(this.pixDims[7])+` +`,n+="Image Offset = "+this.vox_offset+` +`,n+="Data Scale: Slope = "+t(this.scl_slope)+" Intercept = "+t(this.scl_inter)+` +`,n+="Display Range: Max = "+t(this.cal_max)+" Min = "+t(this.cal_min)+` +`,n+="Slice Duration = "+this.slice_duration+` +`,n+="Time Axis Shift = "+this.toffset+` +`,n+="Slice Start = "+this.slice_start+` +`,n+="Slice End = "+this.slice_end+` +`,n+='Description: "'+this.description+`" +`,n+='Auxiliary File: "'+this.aux_file+`" +`,n+="Q-Form Code = "+this.qform_code+" ("+this.getTransformCodeString(this.qform_code)+`) +`,n+="S-Form Code = "+this.sform_code+" ("+this.getTransformCodeString(this.sform_code)+`) +`,n+="Quaternion Parameters: b = "+t(this.quatern_b)+" c = "+t(this.quatern_c)+" d = "+t(this.quatern_d)+` +`,n+="Quaternion Offsets: x = "+this.qoffset_x+" y = "+this.qoffset_y+" z = "+this.qoffset_z+` +`,n+="S-Form Parameters X: "+t(this.affine[0][0])+", "+t(this.affine[0][1])+", "+t(this.affine[0][2])+", "+t(this.affine[0][3])+` +`,n+="S-Form Parameters Y: "+t(this.affine[1][0])+", "+t(this.affine[1][1])+", "+t(this.affine[1][2])+", "+t(this.affine[1][3])+` +`,n+="S-Form Parameters Z: "+t(this.affine[2][0])+", "+t(this.affine[2][1])+", "+t(this.affine[2][2])+", "+t(this.affine[2][3])+` +`,n+="Slice Code = "+this.slice_code+` +`,n+="Units Code = "+this.xyzt_units+" ("+this.getUnitsCodeString(ut.SPATIAL_UNITS_MASK&this.xyzt_units)+", "+this.getUnitsCodeString(ut.TEMPORAL_UNITS_MASK&this.xyzt_units)+`) +`,n+="Intent Code = "+this.intent_code+` +`,n+='Intent Name: "'+this.intent_name+`" +`,n+="Dim Info = "+this.dim_info+` +`,n}getExtensionLocation=function(){return Me.MAGIC_COOKIE+4};getExtensionSize=ut.prototype.getExtensionSize;getExtensionCode=ut.prototype.getExtensionCode;addExtension=ut.prototype.addExtension;removeExtension=ut.prototype.removeExtension;getDatatypeCodeString=ut.prototype.getDatatypeCodeString;getTransformCodeString=ut.prototype.getTransformCodeString;getUnitsCodeString=ut.prototype.getUnitsCodeString;getQformMat=ut.prototype.getQformMat;convertNiftiQFormToNiftiSForm=ut.prototype.convertNiftiQFormToNiftiSForm;convertNiftiSFormToNEMA=ut.prototype.convertNiftiSFormToNEMA;nifti_mat33_mul=ut.prototype.nifti_mat33_mul;nifti_mat33_determ=ut.prototype.nifti_mat33_determ;toArrayBuffer(t=!1){let r=544;if(t)for(let h of this.extensions)r+=h.esize;let c=new Uint8Array(r),l=new DataView(c.buffer);l.setInt32(0,540,this.littleEndian),c.set(new TextEncoder().encode(this.magic),4),l.setInt16(12,this.datatypeCode,this.littleEndian),l.setInt16(14,this.numBitsPerVoxel,this.littleEndian);for(let h=0;h<8;h++)l.setBigInt64(16+8*h,BigInt(this.dims[h]),this.littleEndian);l.setFloat64(80,this.intent_p1,this.littleEndian),l.setFloat64(88,this.intent_p2,this.littleEndian),l.setFloat64(96,this.intent_p3,this.littleEndian);for(let h=0;h<8;h++)l.setFloat64(104+8*h,this.pixDims[h],this.littleEndian);l.setBigInt64(168,BigInt(this.vox_offset),this.littleEndian),l.setFloat64(176,this.scl_slope,this.littleEndian),l.setFloat64(184,this.scl_inter,this.littleEndian),l.setFloat64(192,this.cal_max,this.littleEndian),l.setFloat64(200,this.cal_min,this.littleEndian),l.setFloat64(208,this.slice_duration,this.littleEndian),l.setFloat64(216,this.toffset,this.littleEndian),l.setBigInt64(224,BigInt(this.slice_start),this.littleEndian),l.setBigInt64(232,BigInt(this.slice_end),this.littleEndian),c.set(new TextEncoder().encode(this.description),240),c.set(new TextEncoder().encode(this.aux_file),320),l.setInt32(344,this.qform_code,this.littleEndian),l.setInt32(348,this.sform_code,this.littleEndian),l.setFloat64(352,this.quatern_b,this.littleEndian),l.setFloat64(360,this.quatern_c,this.littleEndian),l.setFloat64(368,this.quatern_d,this.littleEndian),l.setFloat64(376,this.qoffset_x,this.littleEndian),l.setFloat64(384,this.qoffset_y,this.littleEndian),l.setFloat64(392,this.qoffset_z,this.littleEndian);const d=this.affine.flat();for(let h=0;h<12;h++)l.setFloat64(400+8*h,d[h],this.littleEndian);if(l.setInt32(496,this.slice_code,this.littleEndian),l.setInt32(500,this.xyzt_units,this.littleEndian),l.setInt32(504,this.intent_code,this.littleEndian),c.set(new TextEncoder().encode(this.intent_name),508),l.setUint8(524,this.dim_info),t){c.set(Uint8Array.from([1,0,0,0]),540);let h=this.getExtensionLocation();for(const u of this.extensions)l.setInt32(h,u.esize,u.littleEndian),l.setInt32(h+4,u.ecode,u.littleEndian),c.set(new Uint8Array(u.edata),h+8),h+=u.esize}else c.set(new Uint8Array(4).fill(0),540);return c.buffer}}function Hp(i,t=!1){var n,s,r,c;return i.byteLengthv[0]===31&&v[1]===139&&v[2]===8?"gzip":v[0]===120&&[1,94,156,218].includes(v[1])?"deflate":"deflate-raw",s=new Uint8Array(i),r=n(s),c=new DecompressionStream(r),l=new TransformStream({transform(v,y){y.enqueue(v)},flush(v){v.terminate()}}),{readable:d,writable:h}=c,u=h.getWriter(),m=d.pipeThrough(l).getReader();u.write(s).catch(v=>{v instanceof Error&&v.name==="AbortError"||console.error("Error during write:",v)});const g=[];let A=0;try{for(;A=t){await Promise.all([m.cancel().catch(()=>{}),u.abort().catch(()=>{})]);break}}}catch(v){v instanceof Error&&v.name==="AbortError"||console.error("Error during decompression:",v)}finally{await Promise.allSettled([m.cancel().catch(()=>{}),u.close().catch(()=>{})])}return g.length===1?g[0].buffer:g.reduce((v,y)=>{const w=new Uint8Array(v.byteLength+y.byteLength);return w.set(new Uint8Array(v),0),w.set(y,v.byteLength),w.buffer},new ArrayBuffer(0))}function jp(i,t=!1){let n=null;if(su(i)&&(i=Xp(i)),Hp(i,t)?n=new ut:qp(i,t)&&(n=new Me),n)n.readHeader(i);else throw new Error("That file does not appear to be NIFTI!");return n}async function Ka(i,t=!1){if(!su(i))return jp(i,t);let n=null,s=await kd(i,540),r=!0,c=!0;var l=new DataView(s);const d=l.getInt32(0,!0),h=l.getInt32(0,!1);if(d!==348)if(h===348)r=!1;else if(d===540)c=!1;else if(h===540)c=!1,r=!1;else throw new Error("That file does not appear to be NIFTI!");let u=Math.round(l.getFloat32(108,r));return Me&&(u=rt.getUint64At(l,168,r)),u>s.byteLength&&(s=await kd(i,u)),c?n=new ut:n=new Me,n.readHeader(s),n}function Qp(i){return i.extensionFlag[0]!=0}function Yd(i,t){var n=i.vox_offset,s=1,r=1;i.dims[4]&&(s=i.dims[4]),i.dims[5]&&(r=i.dims[5]);var c=i.dims[1]*i.dims[2]*i.dims[3]*s*r*(i.numBitsPerVoxel/8);return t.slice(n,n+c)}function O2(i,t,n,s={}){return t!==void 0&&n!==void 0&&(s={...s,headers:{...s.headers,Range:`bytes=${t}-${t+n-1}`}}),fetch(i,s)}function Zp(i,t){return{...i,...t,headers:{...i.headers,...t.headers}}}function Gd(i,t){const n=typeof i=="string"?new URL(i):i;n.pathname.endsWith("/")||(n.pathname+="/");const s=new URL(t.slice(1),n);return s.search=n.search,s}async function Hd(i){if(i.status!==404){if(i.status===200||i.status===206)return new Uint8Array(await i.arrayBuffer());throw new Error(`Unexpected response status ${i.status} ${i.statusText}`)}}async function Wp(i,t,n,s){if(s)return fetch(i,{...n,headers:{...n.headers,Range:`bytes=-${t}`}});let r=await fetch(i,{...n,method:"HEAD"});if(!r.ok)return r;let c=r.headers.get("Content-Length"),l=Number(c);return O2(i,l-t,l,n)}class _p{url;#t;#e;constructor(t,n={}){this.url=t,this.#t=n.overrides??{},this.#e=n.useSuffixRequest??!1}#i(t){return Zp(this.#t,t)}async get(t,n={}){let s=Gd(this.url,t).href,r=await fetch(s,this.#i(n));return Hd(r)}async getRange(t,n,s={}){let r=Gd(this.url,t),c=this.#i(s),l;return"suffixLength"in n?l=await Wp(r,n.suffixLength,c,this.#e):l=await O2(r,n.offset,n.length,c),Hd(l)}}const Jp="modulepreload",$p=function(i){return"/"+i},qd={},Th=function(t,n,s){let r=Promise.resolve();if(n&&n.length>0){let u=function(m){return Promise.all(m.map(g=>Promise.resolve(g).then(A=>({status:"fulfilled",value:A}),A=>({status:"rejected",reason:A}))))};var l=u;document.getElementsByTagName("link");const d=document.querySelector("meta[property=csp-nonce]"),h=d?.nonce||d?.getAttribute("nonce");r=u(n.map(m=>{if(m=$p(m),m in qd)return;qd[m]=!0;const g=m.endsWith(".css"),A=g?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${m}"]${A}`))return;const v=document.createElement("link");if(v.rel=g?"stylesheet":Jp,g||(v.as="script"),v.crossOrigin="",v.href=m,h&&v.setAttribute("nonce",h),document.head.appendChild(v),g)return new Promise((y,w)=>{v.addEventListener("load",y),v.addEventListener("error",()=>w(new Error(`Unable to preload CSS for ${m}`)))})}))}function c(d){const h=new Event("vite:preloadError",{cancelable:!0});if(h.payload=d,window.dispatchEvent(h),!h.defaultPrevented)throw d}return r.then(d=>{for(const h of d||[])h.status==="rejected"&&c(h.reason);return t().catch(c)})};class z2{#t;constructor(t,n,s){typeof t=="number"?this.#t=new Uint8Array(t):t instanceof ArrayBuffer?this.#t=new Uint8Array(t,n,s):this.#t=new Uint8Array(Array.from(t,r=>r?1:0))}get BYTES_PER_ELEMENT(){return 1}get byteOffset(){return this.#t.byteOffset}get byteLength(){return this.#t.byteLength}get buffer(){return this.#t.buffer}get length(){return this.#t.length}get(t){let n=this.#t[t];return typeof n=="number"?n!==0:n}set(t,n){this.#t[t]=n?1:0}fill(t){this.#t.fill(t?1:0)}*[Symbol.iterator](){for(let t=0;tl):Array.from({length:n},(c,l)=>n-1-l)),ge(n===t.length,"Order length must match the number of dimensions.");let s=1,r=new Array(n);for(let c=t.length-1;c>=0;c--)r[t[c]]=s,s*=i[t[c]];return r}function t5({name:i,configuration:t}){if(i==="default"){const n=t?.separator??"/";return s=>["c",...s].join(n)}if(i==="v2"){const n=t?.separator??".";return s=>s.join(n)||"0"}throw new Error(`Unknown chunk key encoding: ${i}`)}function e5(i){if(i==="|O")return{data_type:"v2:object"};let t=i.match(/^([<|>])(.*)$/);ge(t,`Invalid dtype: ${i}`);let[,n,s]=t,r={b1:"bool",i1:"int8",u1:"uint8",i2:"int16",u2:"uint16",i4:"int32",u4:"uint32",i8:"int64",u8:"uint64",f2:"float16",f4:"float32",f8:"float64"}[s]??(s.startsWith("S")||s.startsWith("U")?`v2:${s}`:void 0);return ge(r,`Unsupported or unknown dtype: ${i}`),n==="|"?{data_type:r}:{data_type:r,endian:n==="<"?"little":"big"}}function i5(i,t={}){let n=[],s=e5(i.dtype);i.order==="F"&&n.push({name:"transpose",configuration:{order:"F"}}),"endian"in s&&s.endian==="big"&&n.push({name:"bytes",configuration:{endian:"big"}});for(let{id:r,...c}of i.filters??[])n.push({name:r,configuration:c});if(i.compressor){let{id:r,...c}=i.compressor;n.push({name:r,configuration:c})}return{zarr_format:3,node_type:"array",shape:i.shape,data_type:s.data_type,chunk_grid:{name:"regular",configuration:{chunk_shape:i.chunks}},chunk_key_encoding:{name:"v2",configuration:{separator:i.dimension_separator??"."}},codecs:n,fill_value:i.fill_value,attributes:t}}function n5(i,t={}){return{zarr_format:3,node_type:"group",attributes:t}}function s5(i,t){if(t!=="number"&&t!=="bigint"&&t!=="boolean"&&t!=="object"&&t!=="string")return i===t;let n=i==="bool";if(t==="boolean")return n;let s=i.startsWith("v2:U")||i.startsWith("v2:S");if(t==="string")return s;let r=i==="int64"||i==="uint64";if(t==="bigint")return r;let c=i==="v2:object";return t==="object"?c:!s&&!r&&!n&&!c}function a5(i){return i?.name==="sharding_indexed"}function k2(i){return(i.data_type==="uint64"||i.data_type==="int64")&&i.fill_value!=null?BigInt(i.fill_value):i.fill_value}function Y2(i,...t){if(!t.some(n=>i instanceof n))throw i}function ge(i,t=""){if(!i)throw new Error(t)}async function G2(i,{format:t,signal:n}){const s=i instanceof Response?i:new Response(i);ge(s.body,"Response does not contain body.");try{return await new Response(s.body.pipeThrough(new DecompressionStream(t),{signal:n})).arrayBuffer()}catch{throw n?.throwIfAborted(),new Error(`Failed to decode ${t}`)}}class ru{kind="array_to_array";constructor(t,n){ge(t.keepbits>=0,"keepbits must be zero or positive")}static fromConfig(t,n){return new ru(t,n)}encode(t){throw new Error("`BitroundCodec.encode` is not implemented. Please open an issue at https://github.com/manzt/zarrita.js/issues.")}decode(t){return t}}const Kd=r5();function r5(){const i=new Uint32Array([305419896]);return new Uint8Array(i.buffer,i.byteOffset,i.byteLength)[0]!==18}function jd(i){return"BYTES_PER_ELEMENT"in i?i.BYTES_PER_ELEMENT:4}class Zl{kind="array_to_bytes";#t;#e;#i;#s;#n;constructor(t,n){this.#n=t?.endian,this.#e=P2(n.data_type),this.#s=n.shape,this.#t=Zn(n.shape,"C");const s=new this.#e(0);this.#i=s.BYTES_PER_ELEMENT}static fromConfig(t,n){return new Zl(t,n)}encode(t){let n=new Uint8Array(t.data.buffer);return Kd&&this.#n==="big"&&Xd(n,jd(this.#e)),n}decode(t){return Kd&&this.#n==="big"&&Xd(t,jd(this.#e)),{data:new this.#e(t.buffer,t.byteOffset,t.byteLength/this.#i),shape:this.#s,stride:this.#t}}}class lu{kind="bytes_to_bytes";static fromConfig(){return new lu}encode(t){throw new Error("Not implemented")}decode(t){return new Uint8Array(t.buffer,t.byteOffset,t.byteLength-4)}}class ou{kind="bytes_to_bytes";static fromConfig(t){return new ou}encode(t){throw new Error("Gzip encoding is not enabled by default. Please register a custom codec with `numcodecs/gzip`.")}async decode(t){const n=await G2(t,{format:"gzip"});return new Uint8Array(n)}}function l5(i,t){return ge(!Number.isNaN(t),"JsonCodec allow_nan is false but NaN was encountered during encoding."),ge(t!==Number.POSITIVE_INFINITY,"JsonCodec allow_nan is false but Infinity was encountered during encoding."),ge(t!==Number.NEGATIVE_INFINITY,"JsonCodec allow_nan is false but -Infinity was encountered during encoding."),t}function o5(i,t){return t instanceof Object&&!Array.isArray(t)?Object.keys(t).sort().reduce((n,s)=>(n[s]=t[s],n),{}):t}class cu{configuration;kind="array_to_bytes";#t;#e;constructor(t={}){this.configuration=t;const{encoding:n="utf-8",skipkeys:s=!1,ensure_ascii:r=!0,check_circular:c=!0,allow_nan:l=!0,sort_keys:d=!0,indent:h,strict:u=!0}=t;let m=t.separators;m||(h?m=[", ",": "]:m=[",",":"]),this.#t={encoding:n,skipkeys:s,ensure_ascii:r,check_circular:c,allow_nan:l,indent:h,separators:m,sort_keys:d},this.#e={strict:u}}static fromConfig(t){return new cu(t)}encode(t){const{indent:n,encoding:s,ensure_ascii:r,check_circular:c,allow_nan:l,sort_keys:d}=this.#t;ge(s==="utf-8","JsonCodec does not yet support non-utf-8 encoding.");const h=[];ge(c,"JsonCodec does not yet support skipping the check for circular references during encoding."),l||h.push(l5),d&&h.push(o5);const u=Array.from(t.data);u.push("|O"),u.push(t.shape);let m;h.length&&(m=(A,v)=>{let y=v;for(let w of h)y=w(A,y);return y});let g=JSON.stringify(u,m,n);return r&&(g=g.replace(/[\u007F-\uFFFF]/g,A=>{const v=`0000${A.charCodeAt(0).toString(16)}`;return`\\u${v.substring(v.length-4)}`})),new TextEncoder().encode(g)}decode(t){const{strict:n}=this.#e;ge(n,"JsonCodec does not yet support non-strict decoding.");const s=nr(t),r=s.pop();s.pop(),ge(r,"0D not implemented for JsonCodec.");const c=Zn(r,"C");return{data:s,shape:r,stride:c}}}function Qd(i){return i instanceof z2||i instanceof au||i instanceof ir?new Proxy(i,{get(n,s){return n.get(Number(s))},set(n,s,r){return n.set(Number(s),r),!0}}):i}function c5(i,t){let n;return i.data instanceof au||i.data instanceof ir?n=new i.constructor(i.data.length,i.data.chars):n=new i.constructor(i.data.length),{data:n,shape:i.shape,stride:Zn(i.shape,t)}}function h5(i,t){let n=c5(i,t),s=i.shape.length,r=i.data.length,c=Array(s).fill(0),l=Qd(i.data),d=Qd(n.data);for(let h=0;h({stride:n,index:s})).sort((n,s)=>s.stride-n.stride).map(n=>n.index)}function f5(i,t){let n=u5(i);return ge(n.length===t.length,"Orders must match"),n.every((s,r)=>s===t[r])}class hu{kind="array_to_array";#t;#e;constructor(t,n){let s=t.order??"C",r=n.shape.length,c=new Array(r),l=new Array(r);if(s==="C")for(let d=0;d{ge(l[d]===void 0,`Invalid permutation: ${JSON.stringify(s)}`),l[d]=h});this.#t=c,this.#e=l}static fromConfig(t,n){return new hu(t,n)}encode(t){return f5(t,this.#e)?t:h5(t,this.#e)}decode(t){return{data:t.data,shape:t.shape,stride:Zn(t.shape,this.#t)}}}class uu{kind="array_to_bytes";#t;#e;constructor(t){this.#t=t,this.#e=Zn(t,"C")}static fromConfig(t,n){return new uu(n.shape)}encode(t){throw new Error("Method not implemented.")}decode(t){let n=new TextDecoder,s=new DataView(t.buffer),r=Array(s.getUint32(0,!0)),c=4;for(let l=0;lTh(()=>import("./blosc-CrUiACa7.js"),__vite__mapDeps([0,1])).then(i=>i.default)).set("lz4",()=>Th(()=>import("./lz4-B_Exjfmr.js"),__vite__mapDeps([2,1])).then(i=>i.default)).set("zstd",()=>Th(()=>import("./zstd-u5eweWyS.js"),__vite__mapDeps([3,1])).then(i=>i.default)).set("gzip",()=>ou).set("zlib",()=>fu).set("transpose",()=>hu).set("bytes",()=>Zl).set("crc32c",()=>lu).set("vlen-utf8",()=>uu).set("json2",()=>cu).set("bitround",()=>ru)}const m5=d5();function Kh(i){let t;return{async encode(n){t||(t=await Zd(i));for(const r of t.array_to_array)n=await r.encode(n);let s=await t.array_to_bytes.encode(n);for(const r of t.bytes_to_bytes)s=await r.encode(s);return s},async decode(n){t||(t=await Zd(i));for(let r=t.bytes_to_bytes.length-1;r>=0;r--)n=await t.bytes_to_bytes[r].decode(n);let s=await t.array_to_bytes.decode(n);for(let r=t.array_to_array.length-1;r>=0;r--)s=await t.array_to_array[r].decode(s);return s}}}async function Zd(i){let t=i.codecs.map(async c=>{let l=await m5.get(c.name)?.();return ge(l,`Unknown codec: ${c.name}`),{Codec:l,meta:c}}),n=[],s,r=[];for await(let{Codec:c,meta:l}of t){let d=c.fromConfig(l.configuration,i);switch(d.kind){case"array_to_array":n.push(d);break;case"array_to_bytes":s=d;break;default:r.push(d)}}return s||(ge(g5(i),`Cannot encode ${i.data_type} to bytes without a codec`),s=Zl.fromConfig({endian:"little"},i)),{array_to_array:n,array_to_bytes:s,bytes_to_bytes:r}}function g5(i){return i.data_type!=="v2:object"}class sr extends Error{constructor(t,n={}){super(`Node not found: ${t}`,n),this.name="NodeNotFoundError"}}class du extends Error{constructor(t){super(`Missing key: ${t}`),this.name="KeyError"}}const Wd=18446744073709551615n;function A5(i,t,n,s){ge(i.store.getRange,"Store does not support range requests");let r=i.store.getRange.bind(i.store),c=t.map((h,u)=>h/s.chunk_shape[u]),l=Kh({data_type:"uint64",shape:[...c,2],codecs:s.index_codecs}),d={};return async h=>{let u=h.map((S,E)=>Math.floor(S/c[E])),m=i.resolve(n(u)).path,g;if(m in d)g=d[m];else{let S=4,E=16*c.reduce((N,U)=>N*U,1),M=await r(m,{suffixLength:E+S});g=d[m]=M?await l.decode(M):null}if(g===null)return;let{data:A,shape:v,stride:y}=g,w=h.map((S,E)=>S%v[E]).reduce((S,E,M)=>S+E*y[M],0),b=A[w],C=A[w+1];if(!(b===Wd&&C===Wd))return r(m,{offset:Number(b),length:Number(C)})}}class _n{store;path;constructor(t,n="/"){this.store=t,this.path=n}resolve(t){let n=new URL(`file://${this.path.endsWith("/")?this.path:`${this.path}/`}`);return new _n(this.store,decodeURIComponent(new URL(t,n).pathname))}}function p5(i){return new _n(i??new Map)}class mu extends _n{kind="group";#t;constructor(t,n,s){super(t,n),this.#t=s}get attrs(){return this.#t.attributes}}function _d(i){return i.find(n=>n.name==="transpose")?.configuration?.order??"C"}const ja=Symbol("zarrita.context");function v5(i){return i[ja]}function x5(i,t){let{configuration:n}=t.codecs.find(a5)??{},s={encode_chunk_key:t5(t.chunk_key_encoding),TypedArray:P2(t.data_type),fill_value:t.fill_value};if(n){let c=_d(n.codecs);return{...s,kind:"sharded",chunk_shape:n.chunk_shape,codec:Kh({data_type:t.data_type,shape:n.chunk_shape,codecs:n.codecs}),get_strides(l){return Zn(l,c)},get_chunk_bytes:A5(i,t.chunk_grid.configuration.chunk_shape,s.encode_chunk_key,n)}}let r=_d(t.codecs);return{...s,kind:"regular",chunk_shape:t.chunk_grid.configuration.chunk_shape,codec:Kh({data_type:t.data_type,shape:t.chunk_grid.configuration.chunk_shape,codecs:t.codecs}),get_strides(c){return Zn(c,r)},async get_chunk_bytes(c,l){let d=s.encode_chunk_key(c),h=i.resolve(d).path;return i.store.get(h,l)}}}let Xl=class extends _n{kind="array";#t;[ja];constructor(t,n,s){super(t,n),this.#t={...s,fill_value:k2(s)},this[ja]=x5(this,s)}get attrs(){return this.#t.attributes}get shape(){return this.#t.shape}get chunks(){return this[ja].chunk_shape}get dtype(){return this.#t.data_type}async getChunk(t,n){let s=this[ja],r=await s.get_chunk_bytes(t,n);if(!r){let c=s.chunk_shape.reduce((d,h)=>d*h,1),l=new s.TypedArray(c);return l.fill(s.fill_value),{data:l,shape:s.chunk_shape,stride:s.get_strides(s.chunk_shape)}}return s.codec.decode(r)}is(t){return s5(this.dtype,t)}};function*y5(i,t,n=1){t===void 0&&(t=i,i=0);for(let s=i;ss[Symbol.iterator]()),n=t.map(s=>s.next());if(n.some(s=>s.done))throw new Error("Input contains an empty iterator.");for(let s=0;;){if(n[s].done){if(t[s]=i[s][Symbol.iterator](),n[s]=t[s].next(),++s>=t.length)return}else yield n.map(({value:r})=>r),s=0;n[s]=t[s].next()}}function b5({start:i,stop:t,step:n},s){if(n===0)throw new Error("slice step cannot be zero");n=n??1;const r=n<0,[c,l]=r?[-1,s-1]:[0,s];return i===null?i=r?l:c:i<0?(i+=s,il&&(i=l),t===null?t=r?c:l:t<0?(t+=s,tl&&(t=l),[i,t,n]}function Ja(i,t,n=null){return t===void 0&&(t=i,i=null),{start:i,stop:t,step:n}}function C5(){const i=[];return{add:t=>i.push(t()),onIdle:()=>Promise.all(i)}}class gu extends Error{constructor(t){super(t),this.name="IndexError"}}function S5(i,t){throw new gu(`too many indicies for array; expected ${t.length}, got ${i.length}`)}function M5(i){throw new gu(`index out of bounds for dimension with length ${i}`)}function E5(){throw new gu("only slices with step >= 1 are supported")}function D5(i,t){i.length>t.length&&S5(i,t)}function T5(i,t){return i=Math.trunc(i),i<0&&(i=t+i),(i>=t||i<0)&&M5(t),i}class U5{dim_sel;dim_len;dim_chunk_len;nitems;constructor({dim_sel:t,dim_len:n,dim_chunk_len:s}){t=T5(t,n),this.dim_sel=t,this.dim_len=n,this.dim_chunk_len=s,this.nitems=1}*[Symbol.iterator](){const t=Math.floor(this.dim_sel/this.dim_chunk_len),n=t*this.dim_chunk_len,s=this.dim_sel-n;yield{dim_chunk_ix:t,dim_chunk_sel:s}}}class Jd{start;stop;step;dim_len;dim_chunk_len;nitems;nchunks;constructor({dim_sel:t,dim_len:n,dim_chunk_len:s}){const[r,c,l]=b5(t,n);this.start=r,this.stop=c,this.step=l,this.step<1&&E5(),this.dim_len=n,this.dim_chunk_len=s,this.nitems=Math.max(0,Math.ceil((this.stop-this.start)/this.step)),this.nchunks=Math.ceil(this.dim_len/this.dim_chunk_len)}*[Symbol.iterator](){const t=Math.floor(this.start/this.dim_chunk_len),n=Math.ceil(this.stop/this.dim_chunk_len);for(const s of y5(t,n)){const r=s*this.dim_chunk_len,c=Math.min(this.dim_len,(s+1)*this.dim_chunk_len),l=c-r;let d=0,h=0;if(this.startc?l:this.stop-r,m=[h,u,this.step],g=Math.ceil((u-h)/this.step),A=[d,d+g,1];yield{dim_chunk_ix:s,dim_chunk_sel:m,dim_out_sel:A}}}}function F5(i,t){let n=[];return i===null?n=t.map(s=>Ja(null)):Array.isArray(i)&&(n=i.map(s=>s??Ja(null))),D5(n,t),n}class B5{dim_indexers;shape;constructor({selection:t,shape:n,chunk_shape:s}){this.dim_indexers=F5(t,n).map((r,c)=>new(typeof r=="number"?U5:Jd)({dim_sel:r,dim_len:n[c],dim_chunk_len:s[c]})),this.shape=this.dim_indexers.filter(r=>r instanceof Jd).map(r=>r.nitems)}*[Symbol.iterator](){for(const t of w5(...this.dim_indexers)){const n=t.map(r=>r.dim_chunk_ix),s=t.map(r=>"dim_out_sel"in r?{from:r.dim_chunk_sel,to:r.dim_out_sel}:{from:r.dim_chunk_sel,to:null});yield{chunk_coords:n,mapping:s}}}}function I5(i,t){return"get"in i?i.get(t):i[t]}async function R5(i,t,n,s){let r=v5(i),c=new B5({selection:t,shape:i.shape,chunk_shape:i.chunks}),l=s.prepare(new r.TypedArray(c.shape.reduce((h,u)=>h*u,1)),c.shape,r.get_strides(c.shape)),d=n.create_queue?.()??C5();for(const{chunk_coords:h,mapping:u}of c)d.add(async()=>{let{data:m,shape:g,stride:A}=await i.getChunk(h,n.opts),v=s.prepare(m,g,A);s.set_from_chunk(l,v,u)});return await d.onIdle(),c.shape.length===0?I5(l.data,0):l}function Au(i,t=0,n){let s=n??i.length-t;return{length:s,subarray(r,c=s){return Au(i,t+r,c-r)},set(r,c=0){for(let l=0;ls.v2?"v3":"v2"}}}async function z5(i){let t=await i.store.get(i.resolve(".zattrs").path);return t?nr(t):{}}async function P5(i,t={}){let n="store"in i?i:new _n(i),s={};return(t.attrs??!0)&&(s=await z5(n)),t.kind==="array"?t2(n,s):t.kind==="group"?e2(n,s):t2(n,s).catch(r=>(Y2(r,sr),e2(n,s)))}async function t2(i,t){let{path:n}=i.resolve(".zarray"),s=await i.store.get(n);if(!s)throw new sr("v2 array",{cause:new du(n)});return Wl.increment(i.store,"v2"),new Xl(i.store,i.path,i5(nr(s),t))}async function e2(i,t){let{path:n}=i.resolve(".zgroup"),s=await i.store.get(n);if(!s)throw new sr("v2 group",{cause:new du(n)});return Wl.increment(i.store,"v2"),new mu(i.store,i.path,n5(nr(s),t))}async function k5(i){let{store:t,path:n}=i.resolve("zarr.json"),s=await i.store.get(n);if(!s)throw new sr("v3 array or group",{cause:new du(n)});let r=nr(s);return r.node_type==="array"&&(r.fill_value=k2(r)),r.node_type==="array"?new Xl(t,i.path,r):new mu(t,i.path,r)}async function Y5(i,t={}){let n="store"in i?i:new _n(i),s=await k5(n);if(Wl.increment(n.store,"v3"),t.kind===void 0||t.kind==="array"&&s instanceof Xl||t.kind==="group"&&s instanceof mu)return s;let r=s instanceof Xl?"array":"group";throw new Error(`Expected node of kind ${t.kind}, found ${r}.`)}async function yn(i,t={}){let n="store"in i?i.store:i,s=Wl.version_max(n),r=s==="v2"?yn.v2:yn.v3,c=s==="v2"?yn.v3:yn.v2;return r(i,t).catch(l=>(Y2(l,sr),c(i,t)))}yn.v2=P5;yn.v3=Y5;var q2=Object.defineProperty,X2=i=>{throw TypeError(i)},G5=(i,t,n)=>t in i?q2(i,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):i[t]=n,_l=(i,t)=>{for(var n in t)q2(i,n,{get:t[n],enumerable:!0})},z=(i,t,n)=>G5(i,typeof t!="symbol"?t+"":t,n),K2=(i,t,n)=>t.has(i)||X2("Cannot "+n),dt=(i,t,n)=>(K2(i,t,"read from private field"),n?n.call(i):t.get(i)),ks=(i,t,n)=>t.has(i)?X2("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(i):t.set(i,n),pn=(i,t,n,s)=>(K2(i,t,"write to private field"),t.set(i,n),n),H5={version:"0.65.0"},q5=new Float32Array([-1,-1,-1,.28,.28,.28,-1,-1,-1,.28,.28,.28,-1,1,-1,.28,.28,.28,1,-1,-1,.28,.28,.28,1,1,-1,.28,.28,.28,1,1,-1,.28,.28,.28,-1,-1,1,.8,.8,.8,-1,-1,1,.8,.8,.8,1,-1,1,.8,.8,.8,-1,1,1,.8,.8,.8,1,1,1,.8,.8,.8,1,1,1,.8,.8,.8,-1,1,-1,0,0,.74,-1,1,-1,0,0,.74,-1,1,1,0,0,.74,1,1,-1,0,0,.74,1,1,1,0,0,.74,1,1,1,0,0,.74,-1,-1,-1,.42,0,.42,-1,-1,-1,.42,0,.42,1,-1,-1,.42,0,.42,-1,-1,1,.42,0,.42,1,-1,1,.42,0,.42,1,-1,1,.42,0,.42,-1,-1,-1,.64,0,0,-1,-1,-1,.64,0,0,-1,-1,1,.64,0,0,-1,1,-1,.64,0,0,-1,1,1,.64,0,0,-1,1,1,.64,0,0,1,-1,-1,0,.5,0,1,-1,-1,0,.5,0,1,1,-1,0,.5,0,1,-1,1,0,.5,0,1,1,1,0,.5,0,1,1,1,0,.5,0,-.45,1,-.8,0,0,0,-.45,1,-.8,0,0,0,-.45,1,.8,0,0,0,-.25,1,-.8,0,0,0,-.25,1,.8,0,0,0,-.25,1,.8,0,0,0,-.25,1,.6,0,0,0,-.25,1,.6,0,0,0,-.25,1,.8,0,0,0,.45,1,.6,0,0,0,.25,1,.8,0,0,0,.25,1,.8,0,0,0,.25,1,.1,0,0,0,.25,1,.1,0,0,0,.25,1,.6,0,0,0,.45,1,.1,0,0,0,.45,1,.6,0,0,0,.45,1,.6,0,0,0,-.25,1,-.1,0,0,0,-.25,1,-.1,0,0,0,-.25,1,.1,0,0,0,.25,1,-.1,0,0,0,.45,1,.1,0,0,0,.45,1,.1,0,0,0,.45,-1,-.8,0,0,0,.45,-1,-.8,0,0,0,.05,-1,.8,0,0,0,.25,-1,-.8,0,0,0,-.15,-1,.8,0,0,0,-.15,-1,.8,0,0,0,-.25,-1,-.8,0,0,0,-.25,-1,-.8,0,0,0,.05,-1,.8,0,0,0,-.45,-1,-.8,0,0,0,-.15,-1,.8,0,0,0,-.15,-1,.8,0,0,0,.13,-1,-.3,0,0,0,.13,-1,-.3,0,0,0,.07,-1,-.1,0,0,0,-.33,-1,-.3,0,0,0,-.27,-1,-.1,0,0,0,-.27,-1,-.1,0,0,0,-.45,.6,1,0,0,0,-.45,.6,1,0,0,0,-.45,.4,1,0,0,0,-.25,.8,1,0,0,0,-.25,.4,1,0,0,0,-.25,.4,1,0,0,0,-.25,.8,1,0,0,0,-.25,.8,1,0,0,0,-.25,.6,1,0,0,0,.25,.8,1,0,0,0,.45,.6,1,0,0,0,.45,.6,1,0,0,0,.25,.8,1,0,0,0,.25,.8,1,0,0,0,.25,-.1,1,0,0,0,.45,.6,1,0,0,0,.45,.1,1,0,0,0,.45,.1,1,0,0,0,-.25,.1,1,0,0,0,-.25,.1,1,0,0,0,-.45,-.1,1,0,0,0,.25,.1,1,0,0,0,.25,-.1,1,0,0,0,.25,-.1,1,0,0,0,-.45,-.1,1,0,0,0,-.45,-.1,1,0,0,0,-.45,-.6,1,0,0,0,-.25,-.1,1,0,0,0,-.25,-.8,1,0,0,0,-.25,-.8,1,0,0,0,-.25,-.6,1,0,0,0,-.25,-.6,1,0,0,0,-.25,-.8,1,0,0,0,.45,-.6,1,0,0,0,.25,-.8,1,0,0,0,.25,-.8,1,0,0,0,.25,-.4,1,0,0,0,.25,-.4,1,0,0,0,.25,-.6,1,0,0,0,.45,-.4,1,0,0,0,.45,-.6,1,0,0,0,.45,-.6,1,0,0,0,-.1,-.8,-1,0,0,0,-.1,-.8,-1,0,0,0,-.1,.8,-1,0,0,0,.1,-.8,-1,0,0,0,.1,.8,-1,0,0,0,.1,.8,-1,0,0,0,-1,-.45,-.8,0,0,0,-1,-.45,-.8,0,0,0,-1,-.45,.8,0,0,0,-1,-.25,-.8,0,0,0,-1,-.25,.8,0,0,0,-1,-.25,.8,0,0,0,-1,-.25,-.8,0,0,0,-1,-.25,-.8,0,0,0,-1,-.25,-.6,0,0,0,-1,.45,-.8,0,0,0,-1,.45,-.6,0,0,0,-1,.45,-.6,0,0,0,1,.45,-.8,0,0,0,1,.45,-.8,0,0,0,1,.45,.8,0,0,0,1,.25,-.8,0,0,0,1,.25,.8,0,0,0,1,.25,.8,0,0,0,1,.25,.6,0,0,0,1,.25,.6,0,0,0,1,.25,.8,0,0,0,1,-.45,.6,0,0,0,1,-.25,.8,0,0,0,1,-.25,.8,0,0,0,1,-.25,.1,0,0,0,1,-.25,.1,0,0,0,1,-.25,.6,0,0,0,1,-.45,.1,0,0,0,1,-.45,.6,0,0,0,1,-.45,.6,0,0,0,1,.25,-.1,0,0,0,1,.25,-.1,0,0,0,1,.25,.1,0,0,0,1,-.25,-.1,0,0,0,1,-.45,.1,0,0,0,1,-.45,.1,0,0,0,1,-.25,-.8,0,0,0,1,-.25,-.8,0,0,0,1,-.05,-.1,0,0,0,1,-.45,-.8,0,0,0,1,-.25,-.1,0,0,0,1,-.25,-.1,0,0,0]),Ot=class{constructor(t,n,s,r,c=null,l=null){z(this,"sphereIdx",[]),z(this,"sphereVtx",[]),z(this,"renderShaders",[]),z(this,"isVisible",!0),z(this,"isPickable",!0),z(this,"vertexBuffer"),z(this,"indexCount"),z(this,"indexBuffer"),z(this,"vao"),z(this,"mode"),z(this,"glFlags",0),z(this,"id"),z(this,"colorId"),z(this,"modelMatrix",Ut()),z(this,"scale",[1,1,1]),z(this,"position",[0,0,0]),z(this,"rotation",[0,0,0]),z(this,"rotationRadians",0),z(this,"extentsMin",[]),z(this,"extentsMax",[]),z(this,"furthestVertexFromOrigin"),z(this,"originNegate"),z(this,"fieldOfViewDeObliqueMM"),z(this,"mm"),this.vertexBuffer=n,this.indexCount=r,this.indexBuffer=c,this.vao=l,this.mode=s,this.id=t,this.colorId=[(t>>0&255)/255,(t>>8&255)/255,(t>>16&255)/255,(t>>24&255)/255]}};z(Ot,"BLEND",1);z(Ot,"CULL_FACE",2);z(Ot,"CULL_FRONT",4);z(Ot,"CULL_BACK",8);z(Ot,"ENABLE_DEPTH_TEST",16);z(Ot,"generateCrosshairs",function(i,t,n,s,r,c,l=20,d=0){const h=Ot.generateCrosshairsGeometry(i,n,s,r,c,l,d);return new Ot(t,h.vertexBuffer,i.TRIANGLES,h.indexCount,h.indexBuffer,h.vao)});z(Ot,"generateCrosshairsGeometry",function(i,t,n,s,r,c=20,l=0){const d=[],h=[],u=r*l;if(u<=0){let v=lt(n[0],t[1],t[2]),y=lt(s[0],t[1],t[2]);Ot.makeCylinder(d,h,v,y,r,c),v=lt(t[0],n[1],t[2]),y=lt(t[0],s[1],t[2]),Ot.makeCylinder(d,h,v,y,r,c),v=lt(t[0],t[1],n[2]),y=lt(t[0],t[1],s[2]),Ot.makeCylinder(d,h,v,y,r,c)}else{let v=lt(n[0],t[1],t[2]),y=lt(t[0]-u,t[1],t[2]);Ot.makeCylinder(d,h,v,y,r,c,!1),v=lt(t[0]+u,t[1],t[2]),y=lt(s[0],t[1],t[2]),Ot.makeCylinder(d,h,v,y,r,c,!1),v=lt(t[0],n[1],t[2]),y=lt(t[0],t[1]-u,t[2]),Ot.makeCylinder(d,h,v,y,r,c,!1),v=lt(t[0],t[1]+u,t[2]),y=lt(t[0],s[1],t[2]),Ot.makeCylinder(d,h,v,y,r,c,!1),v=lt(t[0],t[1],n[2]),y=lt(t[0],t[1],t[2]-u),Ot.makeCylinder(d,h,v,y,r,c,!1),v=lt(t[0],t[1],t[2]+u),y=lt(t[0],t[1],s[2]),Ot.makeCylinder(d,h,v,y,r,c,!1)}const m=i.createBuffer();if(m===null)throw new Error("could not instantiate vertex buffer");i.bindBuffer(i.ARRAY_BUFFER,m),i.bufferData(i.ARRAY_BUFFER,new Float32Array(d),i.STATIC_DRAW);const g=i.createBuffer();if(g===null)throw new Error("could not instantiate index buffer");i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,g),i.bufferData(i.ELEMENT_ARRAY_BUFFER,new Uint32Array(h),i.STATIC_DRAW);const A=i.createVertexArray();return i.bindVertexArray(A),i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,g),i.bindBuffer(i.ARRAY_BUFFER,m),i.enableVertexAttribArray(0),i.vertexAttribPointer(0,3,i.FLOAT,!1,0,0),i.bindVertexArray(null),{vertexBuffer:m,indexBuffer:g,indexCount:h.length,vao:A}});z(Ot,"getFirstPerpVector",function(i){const t=lt(0,0,0);return i[0]===0?t[0]=1:i[1]===0?t[1]=1:i[2]===0?t[2]=1:(t[0]=i[2],t[1]=i[2],t[2]=-(i[0]+i[1]),li(t,t)),t});z(Ot,"subdivide",function(i,t){let n=i.length/3,s=t.length/3;const r=s,c=Gt(),l=Gt();for(let d=0;ddi.levels.debug||console.debug(`${this.name}-debug`,...t)}info(...t){di.levels[this.level]>di.levels.info||console.info(`${this.name}-info`,...t)}warn(...t){di.levels[this.level]>di.levels.warn||console.warn(`${this.name}-warn`,...t)}error(...t){di.levels[this.level]>di.levels.error||console.error(`${this.name}-error`,...t)}fatal(...t){di.levels[this.level]>di.levels.fatal||console.error(`${this.name}-fatal`,...t)}setLogLevel(t){this.level=t}setName(t){this.name=t}};z(j2,"levels",{debug:0,info:1,warn:2,error:3,fatal:4,silent:1/0});var X5=j2,k=new X5({name:"niivue",level:"info"}),kl={};_l(kl,{$itksnap:()=>K5,$slicer3d:()=>j5,actc:()=>Q5,afni_blues_inv:()=>l4,afni_reds_inv:()=>o4,batlow:()=>Z5,bcgwhw:()=>_5,bcgwhw_dark:()=>W5,blue:()=>i3,blue2cyan:()=>t3,blue2magenta:()=>$5,blue2red:()=>J5,bluegrn:()=>e3,bone:()=>n3,bronze:()=>s3,cet_l17:()=>a3,cividis:()=>r3,cool:()=>l3,copper:()=>c3,copper2:()=>o3,ct_airways:()=>h3,ct_artery:()=>u3,ct_bones:()=>f3,ct_brain:()=>m3,ct_brain_gray:()=>d3,ct_cardiac:()=>g3,ct_head:()=>A3,ct_kidneys:()=>p3,ct_liver:()=>v3,ct_muscles:()=>x3,ct_scalp:()=>y3,ct_skull:()=>w3,ct_soft:()=>b3,ct_soft_tissue:()=>C3,ct_surface:()=>S3,ct_vessels:()=>M3,ct_w_contrast:()=>E3,cubehelix:()=>D3,electric_blue:()=>T3,freesurfer:()=>U3,ge_color:()=>F3,gold:()=>B3,gray:()=>I3,green:()=>R3,green2cyan:()=>N3,green2orange:()=>V3,hot:()=>O3,hotiron:()=>L3,hsv:()=>z3,inferno:()=>P3,jet:()=>k3,kry:()=>Y3,linspecer:()=>G3,lipari:()=>H3,magma:()=>q3,mako:()=>X3,navia:()=>K3,nih:()=>j3,plasma:()=>Q3,random:()=>Z3,red:()=>W3,redyell:()=>_3,rocket:()=>J3,roi_i256:()=>c4,surface:()=>$3,thermal:()=>t4,turbo:()=>e4,violet:()=>i4,viridis:()=>n4,warm:()=>s4,winter:()=>a4,x_rain:()=>r4});var K5={R:[0,255,0,0,255,0,255,255,0,205,210,102,0,0,46,255,106,221,233,165,255,147,218,75,255,60,255,255,218,0,188,255,255,222,127,139,124,255,70,0,238,238,240,245,184,32,255,25,112,34,248,245,255,144,173,65,255,250,128,50,244,255,123,255,173,255,127,255,143,220,253,255,0,0,128,255,250,148,178,255,135,100,240,250,255,107,135,0,139,245,186,255,255,0,210,255,47,72,175,128,176,255,139,240,255,216,119,219,72,255,199,154,189,240,230,0,85,64,153,205,250,95,0,255,224,176,138,30,240,152,160],G:[0,0,255,0,255,255,0,239,0,133,180,205,0,139,139,228,90,160,150,42,250,112,112,0,182,179,235,228,165,128,143,105,218,184,255,69,252,255,130,100,130,232,255,222,134,178,20,25,128,139,248,255,160,238,255,105,99,240,0,205,164,255,104,165,216,192,255,140,188,20,245,250,206,255,0,250,128,0,34,127,206,149,230,235,245,142,206,0,0,245,85,228,222,191,105,248,79,61,238,128,224,240,0,255,215,191,136,112,209,0,21,205,183,248,230,250,107,224,50,92,250,158,128,69,255,196,43,144,128,251,82],B:[0,0,0,255,0,255,255,213,205,63,140,170,128,139,87,225,205,221,122,42,250,219,214,130,193,113,205,196,32,128,143,180,185,135,0,19,0,224,180,0,238,170,240,179,11,170,147,112,144,34,255,250,122,144,47,225,71,230,0,50,96,240,238,0,230,203,212,0,143,60,230,240,209,127,128,205,114,211,34,80,235,237,140,215,238,35,250,139,139,220,211,181,173,255,30,220,79,139,238,0,230,245,0,255,0,216,153,147,204,255,133,50,107,255,250,154,47,208,204,92,210,160,0,0,255,222,226,255,128,152,45],A:[0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],I:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130]},j5={labels:["background","tissue","bone","skin","connective tissue","blood","organ","mass","muscle","foreign object","waste","teeth","fat","gray matter","white matter","nerve","vein","artery","capillary","ligament","tendon","cartilage","meniscus","lymph node","lymphatic vessel","cerebro-spinal fluid","bile","urine","feces","gas","fluid","edema","bleeding","necrosis","clot","embolism","head","central nervous system","brain","gray matter of brain","telencephalon","cerebral cortex","right frontal lobe","left frontal lobe","right temporal lobe","left temporal lobe","right parietal lobe","left parietal lobe","right occipital lobe","left occipital lobe","right insular lobe","left insular lobe","right limbic lobe","left limbic lobe","right striatum","left striatum","right caudate nucleus","left caudate nucleus","right putamen","left putamen","right pallidum","left pallidum","right amygdaloid complex","left amygdaloid complex","diencephalon","thalamus","right thalamus","left thalamus","pineal gland","midbrain","substantia nigra","right substantia nigra","left substantia nigra","cerebral white matter","right superior longitudinal fasciculus","left superior longitudinal fasciculus","right inferior longitudinal fasciculus","left inferior longitudinal fasciculus","right arcuate fasciculus","left arcuate fasciculus","right uncinate fasciculus","left uncinate fasciculus","right cingulum bundle","left cingulum bundle","projection fibers","right corticospinal tract","left corticospinal tract","right optic radiation","left optic radiation","right medial lemniscus","left medial lemniscus","right superior cerebellar peduncle","left superior cerebellar peduncle","right middle cerebellar peduncle","left middle cerebellar peduncle","right inferior cerebellar peduncle","left inferior cerebellar peduncle","optic chiasm","right optic tract","left optic tract","right fornix","left fornix","commissural fibers","corpus callosum","posterior commissure","cerebellar white matter","CSF space","ventricles of brain","right lateral ventricle","left lateral ventricle","right third ventricle","left third ventricle","cerebral aqueduct","fourth ventricle","subarachnoid space","spinal cord","gray matter of spinal cord","white matter of spinal cord","endocrine system of brain","pituitary gland","adenohypophysis","neurohypophysis","meninges","dura mater","arachnoid","pia mater","muscles of head","salivary glands","lips","nose","tongue","soft palate","right inner ear","left inner ear","right external ear","left external ear","right middle ear","left middle ear","right eyeball","left eyeball","skull","right frontal bone","left frontal bone","right parietal bone","left parietal bone","right temporal bone","left temporal bone","right sphenoid bone","left sphenoid bone","right ethmoid bone","left ethmoid bone","occipital bone","maxilla","right zygomatic bone","right lacrimal bone","vomer bone","right palatine bone","left palatine bone","mandible","neck","muscles of neck","pharynx","larynx","thyroid gland","right parathyroid glands","left parathyroid glands","skeleton of neck","hyoid bone","cervical vertebral column","thorax","trachea","bronchi","right lung","left lung","superior lobe of right lung","superior lobe of left lung","middle lobe of right lung","inferior lobe of right lung","inferior lobe of left lung","pleura","heart","right atrium","left atrium","atrial septum","ventricular septum","right ventricle of heart","left ventricle of heart","mitral valve","tricuspid valve","aortic valve","pulmonary valve","aorta","pericardium","pericardial cavity","esophagus","thymus","mediastinum","skin of thoracic wall","muscles of thoracic wall","skeleton of thorax","thoracic vertebral column","ribs","sternum","right clavicle","left clavicle","abdominal cavity","abdomen","peritoneum","omentum","peritoneal cavity","retroperitoneal space","stomach","duodenum","small bowel","colon","anus","liver","biliary tree","gallbladder","pancreas","spleen","urinary system","right kidney","left kidney","right ureter","left ureter","urinary bladder","urethra","right adrenal gland","left adrenal gland","female internal genitalia","uterus","right fallopian tube","left fallopian tube","right ovary","left ovary","vagina","male internal genitalia","prostate","right seminal vesicle","left seminal vesicle","right deferent duct","left deferent duct","skin of abdominal wall","muscles of abdominal wall","skeleton of abdomen","lumbar vertebral column","female external genitalia","male external genitalia","skeleton of upper limb","muscles of upper limb","right upper limb","left upper limb","right shoulder","left shoulder","right arm"],R:[0,128,241,177,111,216,221,144,192,220,78,255,230,200,250,244,0,216,183,183,152,111,178,68,111,85,0,214,78,218,170,140,188,216,145,150,177,244,250,200,68,128,83,83,162,162,141,141,182,182,188,188,154,154,177,177,30,30,210,210,48,48,98,98,69,166,122,122,253,145,46,0,0,250,127,127,159,159,125,125,106,106,154,154,126,201,201,78,78,174,174,139,139,148,148,186,186,99,156,156,64,64,138,97,126,194,85,88,88,88,88,88,88,88,88,244,200,250,82,57,60,92,255,255,255,255,201,70,188,177,166,182,229,229,174,174,201,201,194,194,241,203,203,229,229,255,255,209,209,248,248,255,196,255,255,255,242,242,222,177,213,184,150,62,62,62,242,250,255,177,182,175,197,197,172,172,202,224,224,255,206,210,203,233,195,181,152,159,166,218,225,224,255,184,211,47,255,173,188,255,226,253,244,205,205,186,177,255,234,204,180,216,255,205,204,255,221,0,139,249,157,203,185,185,247,247,222,124,249,249,244,255,255,227,213,213,193,216,230,245,245,241,241,177,171,217,212,185,185,198,194,177,177,177,177,177],G:[0,174,214,122,184,101,130,238,104,245,63,250,220,200,250,214,151,101,156,214,189,184,212,172,197,188,145,230,63,255,250,224,65,191,60,98,122,214,250,200,131,174,146,146,115,115,93,93,166,166,135,135,150,150,140,140,111,111,157,157,129,129,153,153,110,113,101,101,135,92,101,108,108,250,150,150,116,116,102,102,174,174,146,146,126,160,160,152,152,140,140,126,126,120,120,135,135,106,171,171,123,123,95,113,161,195,188,106,106,106,106,106,106,106,106,214,200,250,174,157,143,162,244,244,244,244,121,163,91,122,84,105,147,147,122,122,112,112,142,142,213,179,179,204,204,243,243,185,185,223,223,230,172,255,250,237,217,217,198,122,124,105,208,162,162,162,206,210,255,122,228,216,165,165,138,138,164,186,186,245,110,115,108,138,100,85,55,63,70,123,130,97,244,122,171,150,244,121,95,239,202,232,217,179,179,124,122,255,234,142,119,132,253,167,168,224,130,145,150,180,108,136,102,102,182,182,154,186,186,186,170,181,190,153,141,141,123,146,158,172,172,172,172,124,85,198,188,135,135,175,98,122,122,122,122,122],B:[0,128,145,101,210,79,101,144,88,20,0,220,70,235,210,49,206,79,220,211,207,210,242,100,131,255,30,130,0,255,250,228,28,216,66,83,101,49,225,215,98,128,164,164,105,105,137,137,110,110,166,166,201,201,190,190,85,85,166,166,126,126,112,112,53,137,38,38,192,109,131,112,112,225,88,88,163,163,154,154,155,155,83,83,55,133,133,141,141,103,103,177,177,72,72,135,135,24,108,108,147,147,74,158,197,164,255,215,215,215,215,215,215,215,215,49,215,225,128,110,83,109,209,209,209,209,77,117,95,101,94,107,118,118,90,90,73,73,0,0,144,77,77,109,109,152,152,85,85,131,131,138,68,167,160,145,123,123,101,101,109,108,243,114,114,114,142,139,207,101,255,244,145,145,115,115,140,162,162,217,84,89,81,112,73,57,13,27,38,97,104,76,209,154,143,103,209,88,76,172,134,158,154,108,108,161,101,220,194,178,153,105,229,142,143,199,101,30,98,111,162,116,83,83,164,164,132,223,150,150,147,158,165,130,113,113,103,127,140,147,147,151,151,92,68,131,102,134,134,125,79,101,101,101,101,101],A:[0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],I:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]},Q5={R:[0,0,24,248,255],G:[0,0,177,254,0],B:[0,136,0,0,0],A:[0,32,64,78,128],I:[0,64,128,156,255]},Z5={R:[1,10,15,17,21,27,36,49,65,82,99,118,140,161,183,203,222,238,248,253,253,253,252,250],G:[25,42,56,68,79,88,97,105,111,116,122,127,133,138,142,146,150,155,162,170,178,186,195,204],B:[89,92,95,96,98,98,96,91,83,74,64,55,46,43,49,62,79,100,126,151,175,199,223,250],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,11,22,33,44,55,66,77,88,99,110,121,133,144,155,166,177,188,199,210,221,232,243,255]},W5={R:[0,248,242,235,229,222,212,202,193,183,173,145,117,78,39,0,0,0,0,0,0,64,128,191,255,255,255,255,255,238,221,204,214,224,235,245,255,249,242,236,229,223,217,210,204,197,191,184,176,169,161,154,146,139,132,124,117,109,102,0],G:[0,251,247,243,239,235,235,235,235,235,235,216,197,174,150,127,153,178,204,229,255,255,255,255,255,220,185,150,115,77,38,0,31,61,92,122,153,138,122,107,92,77,61,46,31,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0],B:[0,254,253,252,251,250,251,252,253,254,255,226,198,132,66,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40,80,120,160,200,199,198,197,196,196,195,194,193,192,191,184,176,169,161,154,146,139,132,124,117,109,102,0],A:[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256],I:[0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,255]},_5={R:[255,248,242,235,229,222,212,202,193,183,173,145,117,78,39,0,0,0,0,0,0,64,128,191,255,255,255,255,255,238,221,204,214,224,235,245,255,249,242,236,229,223,217,210,204,197,191,184,176,169,161,154,146,139,132,124,117,109,102,0],G:[255,251,247,243,239,235,235,235,235,235,235,216,197,174,150,127,153,178,204,229,255,255,255,255,255,220,185,150,115,77,38,0,31,61,92,122,153,138,122,107,92,77,61,46,31,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0],B:[255,254,253,252,251,250,251,252,253,254,255,226,198,132,66,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40,80,120,160,200,199,198,197,196,196,195,194,193,192,191,184,176,169,161,154,146,139,132,124,117,109,102,0],A:[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256],I:[0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,255]},J5={R:[0,0,0,0,196,255],G:[0,32,128,128,128,32],B:[0,255,196,0,0,0],A:[0,128,64,64,64,128],I:[0,1,64,128,192,255]},$5={R:[0,255],G:[0,0],B:[255,255],A:[0,128],I:[0,255]},t3={R:[0,0],G:[0,255],B:[255,255],A:[0,128],I:[0,255]},e3={R:[0,0,0,0],G:[0,1,128,255],B:[0,222,127,32],A:[0,0,64,128],I:[0,1,128,255]},i3={R:[0,0,0],G:[0,0,0],B:[0,128,255],A:[0,64,128],I:[0,128,255]},n3={R:[0,103,255],G:[0,126,255],B:[0,165,255],A:[0,76,128],I:[0,153,255]},s3={R:[0,43,103,199,216,255],G:[0,0,37,155,213,255],B:[0,0,20,97,201,255],A:[0,44,48,54,56,56],I:[0,64,128,196,240,255]},a3={R:[0,9,24,33,40,46,52,57,62,66,70,74,78,81,85,88,91,94,98,101,103,106,109,112,114,117,119,121,124,126,128,130,133,135,137,139,141,143,145,147,149,151,153,155,157,159,161,163,164,166,168,169,171,172,174,175,177,178,180,181,183,184,186,187,189,190,191,193,194,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,222,223,224,224,225,226,226,227,228,228,229,229,230,231,231,232,233,233,234,234,235,235,236,236,236,237,237,237,238,238,238,239,239,239,240,240,240,241,241,241,242,242,242,243,243,243,243,243,243,243,243,244,244,244,244,244,244,244,244,244,244,244,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,243,243,243,243,243,243,243,243,243,243,243,243,242,242,242,242,242,242,242,242,241,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,243,243,244,244,245,246,246,247,247,248,249,249,250,250,251,251,252,252,253,253,254,254,254],G:[42,41,41,41,40,40,40,39,39,39,38,38,37,37,36,36,35,35,34,34,33,32,32,31,30,30,30,30,29,29,29,29,28,28,28,27,27,27,26,26,26,25,25,25,24,24,24,24,24,25,25,26,27,27,28,28,29,30,30,31,31,32,33,33,34,34,35,36,36,37,38,39,40,42,43,44,45,47,48,49,50,51,53,54,55,56,57,58,59,60,62,63,64,65,66,68,69,71,72,73,75,76,77,79,80,81,83,84,85,87,88,89,90,92,93,94,95,97,98,100,101,102,104,105,107,108,109,111,112,113,115,116,117,119,120,121,122,124,125,126,128,129,130,132,133,134,136,137,138,140,141,142,144,145,146,147,149,150,151,153,154,155,156,158,159,160,161,163,164,165,167,168,169,170,172,173,174,175,176,178,179,180,181,183,184,185,186,187,189,190,191,192,193,194,196,197,198,199,200,201,203,204,205,206,207,208,209,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,228,229,230,231,232,233,234,235,236,237,238,238,239,240,241,241,242,243,244,244,245,246,247,248,248,249,250,251,251,252,253,254,255],B:[167,167,166,166,166,165,165,165,164,164,164,163,163,162,162,162,161,161,161,160,160,160,159,159,158,158,157,157,156,155,155,154,154,153,153,152,151,151,150,150,149,149,148,147,147,146,146,145,144,144,143,143,142,141,141,140,139,139,138,137,137,136,135,135,134,133,133,132,131,131,130,130,129,128,128,127,127,126,125,125,124,124,123,123,122,121,121,120,119,119,118,118,117,116,116,116,115,115,114,114,113,113,113,112,112,111,111,110,110,109,109,109,108,108,107,107,106,106,106,106,106,105,105,105,105,105,105,105,104,104,104,104,104,103,103,103,103,103,102,102,102,103,103,103,103,104,104,104,104,104,105,105,105,105,106,106,106,106,106,107,107,107,107,108,108,109,110,111,111,112,113,113,114,115,115,116,117,117,118,119,120,120,121,122,122,123,124,125,126,128,129,130,131,132,134,135,136,137,138,140,141,142,143,144,146,147,148,149,150,152,153,155,157,158,160,162,163,165,167,168,170,172,173,175,177,178,180,182,183,185,187,188,190,193,196,199,201,204,207,210,212,215,218,221,224,226,229,232,235,238,240,243,246,249,252,255],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]},r3={R:[0,86,166,255],G:[32,92,156,233],B:[76,108,117,69],A:[0,56,80,88],I:[0,64,192,255]},l3={R:[0,0,0],G:[127,196,254],B:[255,255,255],A:[0,64,128],I:[0,128,255]},o3={R:[0,61,122,183,244,255],G:[0,41,81,122,163,255],B:[0,25,51,76,102,255],A:[0,25,51,71,102,128],I:[0,51,102,153,204,255]},c3={R:[0,61,122,183,244,255],G:[0,41,81,122,163,203],B:[0,25,51,76,102,127],A:[0,25,51,71,102,128],I:[0,51,102,153,204,255]},h3={min:-643,max:-235,R:[0,0,0],G:[154,154,154],B:[179,179,101],A:[0,32,0],I:[0,163,255]},u3={min:114,max:800,R:[0,255,255,255],G:[0,0,129,255],B:[0,0,0,255],A:[0,64,88,228],I:[0,80,160,255]},f3={min:180,max:600,R:[0,0,113,255],G:[0,0,109,250],B:[0,0,101,245],A:[0,0,100,160],I:[0,1,128,255]},d3={min:-10,max:110,R:[0,127,255],G:[0,127,255],B:[0,127,255],A:[0,48,128],I:[0,124,255]},m3={min:-10,max:110,R:[0,199,255],G:[0,127,255],B:[0,127,255],A:[0,48,128],I:[0,124,255]},g3={min:-80,max:1e3,R:[0,189,150,150,150,150,255],G:[0,169,54,54,54,54,240],B:[0,153,52,52,52,52,242],A:[0,32,64,0,0,64,64],I:[0,1,82,92,234,242,255]},A3={min:-590,max:600,R:[0,241,241,248,248,178,178,232,255,255,255],G:[0,156,156,222,222,36,36,51,255,255,255],B:[0,130,130,169,169,24,24,37,255,255,255],A:[0,8,0,0,0,64,64,0,0,222,222],I:[0,2,3,64,122,142,172,182,252,253,255]},p3={min:114,max:302,R:[0,255,255],G:[0,129,255],B:[0,0,255],A:[0,88,228],I:[0,103,255]},v3={min:-23,max:246,R:[0,44,255,255,255],G:[0,128,90,255,255],B:[0,0,70,0,255],A:[0,0,82,184,228],I:[0,64,131,196,255]},x3={min:-100,max:246,R:[0,128,159,255,255,255,255],G:[0,0,56,90,0,255,255],B:[0,0,41,70,0,0,255],A:[0,63,105,135,167,184,228],I:[0,100,128,155,180,209,255]},y3={min:-590,max:600,R:[0,241,241,248,248,178,232,255,255],G:[0,156,156,222,222,36,51,255,255],B:[0,130,130,169,169,24,37,255,255],A:[0,63,105,135,167,184,228,228,228],I:[0,1,52,127,137,162,172,252,255]},w3={min:140,max:1024,R:[0,2,113,255],G:[0,1,109,250],B:[0,1,101,245],A:[0,1,96,168],I:[0,1,128,255]},b3={min:-923,max:679,R:[0,0,0,0,0,255,255,255],G:[154,154,154,154,0,0,254,255],B:[179,179,179,179,0,0,0,255],A:[0,3,8,0,0,10,15,20],I:[0,30,62,88,170,200,232,255]},C3={min:-10,max:110,R:[0,199,255],G:[0,127,255],B:[0,127,255],A:[0,48,128],I:[0,124,255]},S3={min:-600,max:100,R:[0,134,255],G:[0,109,250],B:[0,101,245],A:[0,60,148],I:[0,128,255]},M3={min:114,max:246,R:[0,255,255],G:[0,128,255],B:[0,128,255],A:[0,64,96],I:[0,87,255]},E3={min:50,max:1e3,R:[98,210,169,128,255],G:[94,26,77,128,255],B:[45,21,74,128,255],A:[0,25,0,4,168],I:[0,41,87,154,255]},D3={R:[0,13,21,26,27,25,22,21,22,28,39,54,75,98,124,148,171,189,202,210,213,211,206,200,195,193,195,201,211,225,240,255],G:[0,5,11,20,31,44,58,72,86,99,109,116,120,122,122,122,121,121,124,129,137,147,161,175,190,205,218,229,238,245,251,255],B:[0,14,30,46,61,71,77,78,75,68,60,52,48,47,53,65,83,105,131,157,183,205,222,235,241,243,242,240,239,240,245,255],A:[0,4,8,12,17,21,25,29,33,37,41,45,50,54,58,62,66,70,74,78,83,87,91,95,99,103,107,111,116,120,124,128],I:[0,8,16,25,33,41,49,58,66,74,82,90,99,107,115,123,132,140,148,156,165,173,181,189,197,206,214,222,230,239,247,255]},T3={R:[0,10,136,255],G:[0,39,220,255],B:[0,223,253,255],A:[0,48,64,70],I:[0,92,192,255]},U3={R:[0,245,205,120,196,220,230,0,122,236,12,204,42,119,220,103,60,255,165,160,0,245,205,120,196,220,230,0,122,236,13,220,103,255,165,160,0,120,200,255,255,164,164,164,234,0,0,0,0,0],G:[0,245,62,18,58,248,148,118,186,13,48,182,204,159,216,255,60,165,42,32,200,245,62,18,58,248,148,118,186,13,48,216,255,165,42,32,200,190,70,148,148,108,108,108,169,0,0,0,0,0],B:[0,245,78,134,250,164,34,14,220,176,255,142,164,176,20,255,60,0,42,240,200,245,78,134,250,164,34,14,220,176,255,20,255,0,42,240,221,150,255,10,10,226,226,226,30,64,112,160,208,255],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,2,3,4,5,7,8,10,11,12,13,14,15,16,17,18,24,26,28,30,31,41,42,43,44,46,47,49,50,51,52,53,54,58,60,62,63,72,77,78,79,80,81,82,85,251,252,253,254,255]},F3={R:[0,0,128,255,255],G:[0,128,0,128,255],B:[0,125,255,0,255],A:[0,32,64,96,128],I:[0,63,128,192,255]},B3={R:[0,142,227,255],G:[0,85,170,255],B:[0,14,76,255],A:[0,42,84,128],I:[0,85,170,255]},I3={R:[0,255],G:[0,255],B:[0,255],A:[0,128],I:[0,255]},R3={R:[0,0,0],G:[0,128,255],B:[0,0,0],A:[0,64,128],I:[0,128,255]},N3={R:[0,0,0],G:[72,72,255],B:[0,255,255],A:[0,64,128],I:[0,88,255]},V3={R:[0,255,255],G:[72,88,255],B:[0,0,0],A:[0,64,128],I:[0,88,255]},L3={R:[0,255,255,255],G:[0,0,126,255],B:[0,0,0,255],A:[0,64,96,128],I:[0,128,191,255]},O3={R:[3,255,255,255],G:[0,0,255,255],B:[0,0,0,255],A:[0,48,96,128],I:[0,95,191,255]},z3={R:[255,255,0,0,0,255,255],G:[0,255,255,255,0,0,0],B:[0,0,0,255,255,255,0],A:[0,14,28,43,57,71,85],I:[0,43,85,128,170,213,255]},P3={R:[0,120,237,240],G:[0,28,105,249],B:[4,109,37,33],A:[0,56,80,88],I:[0,64,192,255]},k3={R:[0,0,127,255,127],G:[0,127,255,127,0],B:[127,255,127,0,0],A:[0,32,64,96,128],I:[0,63,128,192,255]},Y3={R:[0,255,255],G:[0,0,255],B:[0,0,0],A:[0,64,64],I:[0,86,255]},G3={R:[94,50,90,152,215,238,249,254,252,241,209,158],G:[79,131,186,214,240,244,237,210,157,100,57,1],B:[162,189,167,164,155,169,168,123,86,68,79,66],A:[0,12,23,35,47,58,70,81,93,105,116,128],I:[0,23,46,70,93,116,139,162,185,209,232,255]},H3={R:[3,7,13,25,45,67,84,98,110,124,138,154,173,191,210,225,233,233,231,229,230,235,243,253],G:[19,33,48,63,77,87,92,94,95,96,96,97,99,101,106,118,133,149,163,177,192,208,225,245],B:[38,58,79,99,114,122,122,120,117,113,110,105,101,97,94,96,103,112,122,134,149,169,192,218],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,11,22,33,44,55,66,77,88,99,110,121,133,144,155,166,177,188,199,210,221,232,243,255]},q3={R:[0,148,183,223,247,252],G:[0,44,55,74,112,253],B:[4,128,121,104,92,191],A:[0,44,53,64,75,107],I:[0,107,128,154,179,255]},X3={R:[11,59,55,222],G:[4,45,165,245],B:[5,91,172,229],A:[0,23,70,107],I:[0,56,167,255]},K3={R:[3,5,6,8,12,19,28,36,42,48,54,61,68,76,86,96,110,129,154,181,205,224,239,252],G:[19,32,44,58,72,86,98,108,116,122,128,134,141,149,157,167,178,191,204,216,225,232,239,244],B:[39,60,82,104,123,137,144,145,142,138,134,130,126,121,116,110,105,104,112,131,155,178,198,217],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,11,22,33,44,55,66,77,88,99,110,121,133,144,155,166,177,188,199,210,221,232,243,255]},j3={R:[0,85,0,0,0,0,0,0,85,255,255,255,172],G:[0,0,0,0,85,170,255,255,255,255,85,0,0],B:[0,170,85,255,255,170,170,0,85,0,0,0,0],A:[0,5,10,21,26,32,37,42,48,53,64,72,85],I:[0,15,31,63,79,95,111,127,143,159,191,217,255]},Q3={R:[13,156,237,240],G:[8,23,121,249],B:[135,158,83,33],A:[0,56,80,88],I:[0,64,192,255]},Z3={R:[208,71,33,192,32,195,208,173,233,202,25,210,145,89,87,245,246,38,3,25,57,167,245,86,227,208,81,64,90,199,140,48,212,180,70,120,9,192,245,177,65,157,9,193,100,181,125,145,62,8,108,36,140,237,242,248,161,189,41,114,65,121,97,50,238,149,44,214,124,167,40,167,127,178,231,30,173,244,193,203,204,238,139,135,71,234,234,217,66,14,129,19,97,165,112,244,35,73,192,12,149,71,33,192,32,195,208,173,233,202,25,210,145,89,87,245,246,38,3,25,57,167,245,86,227,208,81,64,90,199,140,48,212,180,70,120,9,192,245,177,65,157,9,193,100,181,125,145,62,8,108,36,140,237,242,248,161,189,41,114,65,121,97,50,238,149,44,214,124,167,40,167,127,178,231,30,173,244,193,203,204,238,139,135,71,234,234,217,66,14,129,19,97,165,112,244,35,73,192,12,149,71,33,192,32,195,208,173,233,202,25,210,145,89,87,245,246,38,3,25,57,167,245,86,227,208,81,64,90,199,140,48,212,180,70,120,9,192,245,177,65,157,9,193,100,181,125,145,62,8,108,36,140,237,242,248],G:[182,46,78,199,79,89,41,208,135,20,154,35,21,43,230,113,191,147,208,37,28,27,86,203,25,209,148,187,139,111,48,102,76,110,106,130,37,160,34,222,90,165,245,222,102,47,19,130,4,232,137,211,240,11,140,21,42,22,241,61,99,115,199,166,114,190,204,60,233,66,115,230,125,103,203,125,13,176,94,131,39,198,167,124,67,175,254,1,15,198,62,237,159,31,218,58,244,47,61,67,94,46,78,199,79,89,41,208,135,20,154,35,21,43,230,113,191,147,208,37,28,27,86,203,25,209,148,187,139,111,48,102,76,110,106,130,37,160,34,222,90,165,245,222,102,47,19,130,4,232,137,211,240,11,140,21,42,22,241,61,99,115,199,166,114,190,204,60,233,66,115,230,125,103,203,125,13,176,94,131,39,198,167,124,67,175,254,1,15,198,62,237,159,31,218,58,244,47,61,67,94,46,78,199,79,89,41,208,135,20,154,35,21,43,230,113,191,147,208,37,28,27,86,203,25,209,148,187,139,111,48,102,76,110,106,130,37,160,34,222,90,165,245,222,102,47,19,130,4,232,137,211,240,11,140,21],B:[191,154,43,10,207,204,164,231,136,58,239,30,147,230,101,111,150,35,128,57,252,79,173,120,25,126,81,85,8,7,122,237,190,152,246,182,130,219,67,76,167,178,235,250,28,61,186,250,199,67,58,50,86,182,108,77,89,112,59,125,226,50,205,227,125,128,104,27,59,66,53,133,159,203,97,125,139,159,158,7,215,47,140,226,223,231,44,110,184,61,233,47,67,148,22,120,173,156,117,181,94,154,43,10,207,204,164,231,136,58,239,30,147,230,101,111,150,35,128,57,252,79,173,120,25,126,81,85,8,7,122,237,190,152,246,182,130,219,67,76,167,178,235,250,28,61,186,250,199,67,58,50,86,182,108,77,89,112,59,125,226,50,205,227,125,128,104,27,59,66,53,133,159,203,97,125,139,159,158,7,215,47,140,226,223,231,44,110,184,61,233,47,67,148,22,120,173,156,117,181,94,154,43,10,207,204,164,231,136,58,239,30,147,230,101,111,150,35,128,57,252,79,173,120,25,126,81,85,8,7,122,237,190,152,246,182,130,219,67,76,167,178,235,250,28,61,186,250,199,67,58,50,86,182,108,77],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]},W3={R:[0,128,255],G:[0,0,0],B:[0,0,0],A:[0,64,128],I:[0,128,255]},_3={R:[192,224,255],G:[1,128,255],B:[0,0,0],A:[0,64,128],I:[0,128,255]},J3={R:[3,112,144,188,236,246,255],G:[5,31,29,22,76,158,250],B:[26,87,91,86,62,117,235],A:[0,30,38,49,67,85,107],I:[0,73,92,118,160,205,255]},$3={R:[1,240,255],G:[1,128,255],B:[1,128,255],A:[0,76,128],I:[0,153,255]},t4={R:[0,5,18,34,53,72,90,107,126,144,161,178,194,209,222,233,242,248,251,251,249,244,241,252],G:[0,4,10,11,9,11,17,23,30,36,43,50,59,70,83,98,117,136,157,177,199,220,240,254],B:[3,24,50,76,96,106,109,110,108,104,97,89,79,67,55,42,26,12,6,22,47,79,121,164],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,11,22,33,44,55,66,77,88,99,110,121,133,144,155,166,177,188,199,210,221,232,243,255]},e4={R:[48,48,64,70,65,25,132,195,244,254,218,122],G:[18,18,64,107,150,226,255,241,199,158,57,4],B:[59,59,162,227,255,187,81,52,58,47,7,3],A:[0,22,26,30,34,43,52,57,63,67,77,86],I:[0,1,16,32,49,83,118,140,164,181,219,255]},i4={R:[0,128,255],G:[0,0,0],B:[0,128,255],A:[0,64,128],I:[0,128,255]},n4={R:[68,49,53,253],G:[1,104,183,231],B:[84,142,121,37],A:[0,56,80,88],I:[0,64,192,255]},s4={R:[255,255,255],G:[127,196,254],B:[0,0,0],A:[0,64,128],I:[0,128,255]},a4={R:[0,0,0],G:[0,128,255],B:[255,196,128],A:[0,64,128],I:[0,128,255]},r4={R:[3,64,0,0,255,255,255],G:[0,0,0,255,255,192,3],B:[0,32,48,56,64,96,128],A:[0,8,16,24,32,52,80],I:[0,32,64,96,160,192,255]},l4={min:0,max:0,R:[0,37],G:[242,0],B:[255,255],A:[0,64],I:[0,255]},o4={R:[255,255],G:[255,11],B:[0,0],A:[0,64],I:[0,255]},c4={min:0,max:0,R:[65,10,223,120,216,207,251,93,252,217,21,253,131,165,173,143,144,217,86,89,63,254,172,1,142,107,42,78,221,8,222,71,127,126,167,33,104,2,208,216,0,251,7,105,2,101,248,190,253,62,255,224,166,37,110,138,45,34,6,37,69,201,43,122,199,37,173,194,103,211,75,159,96,4,239,98,110,193,253,166,40,255,48,130,140,243,101,9,177,220,133,32,4,81,48,48,210,109,60,132,1,119,1,159,247,33,212,187,253,144,196,254,168,79,64,196,39,97,73,173,104,216,217,43,101,119,254,5,237,103,203,122,57,87,251,164,19,75,200,2,252,150,66,0,255,157,23,254,55,16,240,161,69,253,207,195,5,60,255,251,200,217,134,123,253,180,27,246,130,136,250,232,4,125,140,22,253,255,13,180,123,61,254,111,10,185,76,192,255,223,186,61,198,5,172,13,83,172,171,6,23,73,134,133,109,61,213,55,57,132,36,209,2,144,1,253,68,155,3,160,2,77,121,70,67,176,223,131,4,162,232,255,150,94,235,191,207,10,246,0,225,4,209,116,57,112,172,253,1,6,92,227,73,62,135,223],G:[162,50,112,245,4,124,176,243,56,125,183,139,182,68,189,4,225,10,20,223,7,46,31,193,225,250,219,41,2,100,83,181,34,150,72,223,168,248,80,253,7,117,214,2,248,10,3,59,179,160,90,244,146,4,207,4,125,255,96,100,1,208,130,51,116,181,236,53,244,5,165,28,181,86,96,42,254,1,134,194,214,92,41,204,137,86,207,3,143,3,100,239,164,94,65,251,131,244,173,57,143,107,217,53,210,0,148,250,45,198,81,40,61,218,252,88,171,0,248,24,248,4,41,100,187,46,208,145,43,168,121,46,175,250,125,107,233,112,207,231,174,215,53,9,43,153,52,124,128,65,210,147,255,147,63,200,148,254,0,179,241,42,239,2,230,8,82,135,87,16,3,87,86,151,254,8,255,86,53,19,7,192,171,201,253,247,197,103,251,126,0,149,54,183,61,126,79,113,10,103,184,75,11,195,222,136,149,131,8,99,240,177,252,255,198,16,7,68,178,66,191,150,73,26,211,109,78,209,240,254,1,166,247,131,2,0,167,127,133,10,43,99,235,3,214,142,176,82,132,38,10,249,255,215,44,81],B:[176,182,248,37,117,35,96,69,32,152,108,20,237,250,2,89,141,216,111,251,211,149,10,44,214,103,31,251,3,32,252,246,97,1,219,167,197,4,36,116,206,118,106,43,205,204,114,69,127,205,87,80,41,251,145,204,253,161,247,1,149,9,43,253,97,72,136,161,171,181,26,255,108,80,218,214,231,255,84,31,109,4,218,3,217,36,68,85,241,39,221,2,240,2,173,42,206,5,110,46,103,27,212,184,2,207,246,45,116,72,110,253,38,105,248,159,243,81,192,93,141,145,24,157,234,131,57,178,62,75,65,176,148,40,253,66,76,240,51,154,17,251,139,253,207,9,114,49,200,254,96,73,138,118,204,102,137,89,145,161,4,112,66,234,147,178,212,205,185,11,203,131,2,250,118,169,1,185,154,53,171,197,61,175,249,96,15,254,95,5,222,75,246,194,2,61,180,25,133,165,15,233,59,35,221,140,109,7,114,255,198,0,115,168,252,23,242,80,75,142,137,255,12,182,68,201,4,111,37,228,83,248,24,192,249,5,54,223,160,122,160,114,145,119,252,31,253,250,10,214,8,47,0,142,222,70],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]},h4=class{constructor(){z(this,"gamma",1),z(this,"version",.1),z(this,"cluts",{});const t=Object.keys(kl).filter(n=>!n.startsWith("$")).sort(new Intl.Collator("en").compare);for(const n of t)this.cluts[n]=kl[n]}addColormap(i,t){this.cluts[i]=t}colormaps(){return Object.keys(this.cluts)}colorMaps(){return this.colormaps()}colormapFromKey(i){let t=this.cluts[i];return t!==void 0||(t=this.cluts[i.toLowerCase()],t!==void 0)?t:(i.length>0&&k.warn("No color map named "+i),{min:0,max:0,R:[0,255],G:[0,255],B:[0,255],A:[0,255],I:[0,255]})}colormap(i="",t=!1){const n=this.colormapFromKey(i);return this.makeLut(n.R,n.G,n.B,n.A,n.I,t)}makeLabelLut(i,t=255,n=1/0){if(i.R===void 0||i.G===void 0||i.B===void 0)throw new Error(`Invalid colormap table: ${i}`);const s=i.R.length,r=i.I??[...Array(s).keys()];let c=!1;for(let A=0;An&&(c=!0,r[A]=n);if(c&&k.warn("Some colormap indices clamped to match label range."),s!==i.G.length||s!==i.B.length||s!==r.length)throw new Error(`colormap does not make sense: ${i} Rs ${i.R.length} Gs ${i.G.length} Bs ${i.B.length} Is ${r.length}`);let l=new Uint8ClampedArray(s).fill(t);l[0]=0,i.A!==void 0&&(l=Uint8ClampedArray.from(i.A));const d=Math.min(...r),h=Math.max(...r),u=h-d+1,m=new Uint8ClampedArray(u*4).fill(0);for(let A=0;A0)for(let l=0;l"u"){g=new Uint8ClampedArray(l).fill(0);for(let v=0;v"u"&&(m=new Uint8ClampedArray(l).fill(64),m[0]=0);for(let v=0;v0&&(s[l]=!0);const r=t.length/3;let c=0;for(let l=0;l{document.body.removeChild(r),URL.revokeObjectURL(s)},0)}static async saveMesh(i,t,n=".mz3",s=!1){let r=new ArrayBuffer(0);return/\.obj$/i.test(n)?r=this.createOBJ(i,t):/\.stl$/i.test(n)?r=this.createSTL(i,t):(/\.mz3$/i.test(n)||(n+=".mz3"),r=await this.createMZ3Async(i,t,s)),n.length>4&&this.downloadArrayBuffer(r,n),r}static getClusterBoundary(i,t){const n=new Uint32Array(i.buffer),s=new Array(n.length).fill(!1),r=t.length/3;let c=0;for(let l=0;l0&&(b=1/Math.sqrt(b),n[0]*=b,n[1]*=b,n[2]*=b),y[s]=n[0],y[s+1]=n[1],y[s+2]=n[2]}return y}},yt,ze,Yl,Qh,Qa,Q2=class{constructor(i){ks(this,yt),ks(this,ze,0),ks(this,Yl,[]),ks(this,Qh,[]),ks(this,Qa),pn(this,yt,new DataView(i)),this.read()}async extract(i){const t=new Uint8Array(dt(this,yt).buffer.slice(i.startsAt,i.startsAt+i.compressedSize));if(i.compressionMethod===0)return t;if(i.compressionMethod===8){const n=new DecompressionStream("deflate-raw"),s=n.writable.getWriter();s.write(t).catch(console.error);const r=s.close().catch(console.error),c=new Response(n.readable),l=new Uint8Array(await c.arrayBuffer());return await r,l}throw new Error(`Unsupported compression method: ${i.compressionMethod}`)}read(){for(;!dt(this,Qa)&&dt(this,ze)=16){n=Number(dt(this,yt).getBigUint64(l,!0)),l+=8,t=Number(dt(this,yt).getBigUint64(l,!0)),d=!0;break}else throw new Error(`ZIP64 extra field found but is too small (expected at least 16 bytes, got ${u}).`);l+=u}if(!d)throw new Error("ZIP64 format missing extra field with signature 0x0001.")}return{signature:this.readString(i,4),version:dt(this,yt).getUint16(i+4,!0),generalPurpose:dt(this,yt).getUint16(i+6,!0),compressionMethod:dt(this,yt).getUint16(i+8,!0),lastModifiedTime:dt(this,yt).getUint16(i+10,!0),lastModifiedDate:dt(this,yt).getUint16(i+12,!0),crc:dt(this,yt).getUint32(i+14,!0),compressedSize:t,uncompressedSize:n,fileNameLength:s,extraLength:r,fileName:this.readString(i+30,s),extra:this.readString(i+30+s,r)}}readCentralDirectory(i){return{versionCreated:dt(this,yt).getUint16(i+4,!0),versionNeeded:dt(this,yt).getUint16(i+6,!0),fileNameLength:dt(this,yt).getUint16(i+28,!0),extraLength:dt(this,yt).getUint16(i+30,!0),fileCommentLength:dt(this,yt).getUint16(i+32,!0),diskNumber:dt(this,yt).getUint16(i+34,!0),internalAttributes:dt(this,yt).getUint16(i+36,!0),externalAttributes:dt(this,yt).getUint32(i+38,!0),offset:dt(this,yt).getUint32(i+42,!0),comments:this.readString(i+46,dt(this,yt).getUint16(i+32,!0))}}readEndCentralDirectory(i){const t=dt(this,yt).getUint16(i+20,!0);return{numberOfDisks:dt(this,yt).getUint16(i+4,!0),centralDirectoryStartDisk:dt(this,yt).getUint16(i+6,!0),numberCentralDirectoryRecordsOnThisDisk:dt(this,yt).getUint16(i+8,!0),numberCentralDirectoryRecords:dt(this,yt).getUint16(i+10,!0),centralDirectorySize:dt(this,yt).getUint32(i+12,!0),centralDirectoryOffset:dt(this,yt).getUint32(i+16,!0),commentLength:t,comment:this.readString(i+22,t)}}readEndCentralDirectory64(i){const t=Number(dt(this,yt).getBigUint64(i+0,!0));return{numberOfDisks:dt(this,yt).getUint32(i+16,!0),centralDirectoryStartDisk:dt(this,yt).getUint32(i+20,!0),numberCentralDirectoryRecordsOnThisDisk:Number(dt(this,yt).getBigUint64(i+24,!0)),numberCentralDirectoryRecords:Number(dt(this,yt).getBigUint64(i+32,!0)),centralDirectorySize:Number(dt(this,yt).getBigUint64(i+40,!0)),centralDirectoryOffset:Number(dt(this,yt).getBigUint64(i+48,!0)),commentLength:t,comment:""}}readString(i,t){return Array.from({length:t},(n,s)=>String.fromCharCode(dt(this,yt).getUint8(i+s))).join("")}get entries(){return dt(this,Yl)}};yt=new WeakMap;ze=new WeakMap;Yl=new WeakMap;Qh=new WeakMap;Qa=new WeakMap;var At=class Ys{static arrayBufferToBase64(t){const n=new Uint8Array(t);return Ys.uint8tob64(n)}static async decompress(t){const n=t[0]===31&&t[1]===139&&t[2]===8?"gzip":t[0]===120&&(t[1]===1||t[1]===94||t[1]===156||t[1]===218)?"deflate":"deflate-raw",s=new DecompressionStream(n),r=s.writable.getWriter();r.write(t).catch(console.error);const c=r.close().catch(console.error),l=new Response(s.readable),d=new Uint8Array(await l.arrayBuffer());return await c,d}static async decompressToBuffer(t){const n=await Ys.decompress(t);return n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength)}static async readMatV4(t,n=!1){let s=t.byteLength;if(s<40)throw new Error("File too small to be MAT v4: bytes = "+t.byteLength);let r=new DataView(t),c=r.getUint16(0,!0),l=t;if(c===35615||c===8075){const y=await this.decompress(new Uint8Array(t));r=new DataView(y.buffer),c=r.getUint16(0,!0),l=y.buffer,s=l.byteLength}const d=new TextDecoder("utf-8"),h=new Uint8Array(l);let u=0;const m={};function g(y){return Math.floor(y/10)%10}function A(y,w,b){const C=new Uint8Array(h.subarray(w,b));return y===1?new Float32Array(C.buffer):y===2?new Int32Array(C.buffer):y===3?new Int16Array(C.buffer):y===4?new Uint16Array(C.buffer):y===5?new Uint8Array(C.buffer):new Float64Array(C.buffer)}function v(){const y=r.getUint32(u,!0),w=r.getUint32(u+4,!0),b=r.getUint32(u+8,!0),C=r.getUint32(u+12,!0),S=r.getUint32(u+16,!0);if(u+=20,C!==0)throw new Error("Matlab V4 reader does not support imaginary numbers");const E=w*b;if(E<1)throw new Error("mrows * ncols must be greater than one");const M=new Uint8Array(h.subarray(u,u+S));let N=d.decode(M).trim().replaceAll("\0","");n&&(N=N.replaceAll(".","_"));const U=g(y);let T=8;if(U>=1&&U<=2)T=4;else if(U>=3&&U<=4)T=2;else if(U===5)T=1;else if(U!==0)throw new Error("impossible Matlab v4 datatype");if(u+=S,y>50)throw new Error("Does not appear to be little-endian V4 Matlab file");const F=u+E*T;m[N]=A(U,u,F),u=F}for(;u+20>18,h=(g&258048)>>12,u=(g&4032)>>6,m=g&63,n+=s[d]+s[h]+s[u]+s[m];return c===1?(g=t[l],d=(g&252)>>2,h=(g&3)<<4,n+=s[d]+s[h]+"=="):c===2&&(g=t[l]<<8|t[l+1],d=(g&64512)>>10,h=(g&1008)>>4,u=(g&15)<<2,n+=s[d]+s[h]+s[u]+"="),n}static download(t,n,s){const r=document.createElement("a"),c=Array.isArray(t)?t:[t],l=new Blob(c,{type:s});r.href=URL.createObjectURL(l),r.download=n,r.click()}static readFileAsync(t){return new Promise((n,s)=>{const r=new FileReader;r.onload=()=>{n(r.result)},r.onerror=s,r.readAsArrayBuffer(t)})}static blobToBase64(t){return new Promise(n=>{const s=new FileReader;s.onloadend=()=>n(s.result),s.readAsDataURL(t)})}static async decompressBase64String(t){const n=atob(t),s=new ArrayBuffer(n.length),r=new Uint8Array(s);for(let c=0;c((m==null||m>h.length)&&(m=h.length),new Uint8Array(h.subarray(u,m)));let c=new Uint8Array(t.length+(t.length>>1)),l=0;const d=h=>{c[l++]=h};for(let h=0;hc.length){const m=new Uint8Array(l+8+(s-h<<1));m.set(c),c=m}let u=t.charCodeAt(h);u<128||n?d(u):u<2048?(d(192|u>>6),d(128|u&63)):(u>55295&&u<57344,u=65536+(u&1047552)|t.charCodeAt(++h)&1023,d(240|u>>18),d(128|u>>12&63),d(128|u>>6&63),d(128|u&63))}return r(c,0,l)}static async compress(t,n="gzip"){const s=new CompressionStream(n),r=s.writable.getWriter();r.write(t).catch(console.error);const c=r.close().catch(console.error),d=await new Response(s.readable).arrayBuffer();return await c,d}static async compressStringToArrayBuffer(t){const n=this.strToU8(t);return await this.compress(n)}static isArrayBufferCompressed(t){if(t&&t.byteLength){const n=new Uint8Array(t);return(n[0]<<8|n[1])===8075}else return!1}static strFromU8(t,n){if(n){let s="";for(let r=0;r((h==null||h<0)&&(h=0),(u==null||u>d.length)&&(u=d.length),new Uint8Array(d.subarray(h,u))),r=d=>{for(let h="",u=0;;){let m=d[u++];const g=(m>127)+(m>223)+(m>239);if(u+g>d.length)return{s:h,r:s(d,u-1)};g?g===3?(m=((m&15)<<18|(d[u++]&63)<<12|(d[u++]&63)<<6|d[u++]&63)-65536,h+=String.fromCharCode(55296|m>>10,56320|m&1023)):g&1?h+=String.fromCharCode((m&31)<<6|d[u++]&63):h+=String.fromCharCode((m&15)<<12|(d[u++]&63)<<6|d[u++]&63):h+=String.fromCharCode(m)}},{s:c,r:l}=r(t);if(l.length)throw new Error("Unexpected trailing bytes in UTF-8 decoding");return c}}static async decompressArrayBuffer(t){const n=await this.decompress(new Uint8Array(t));return this.strFromU8(n)}static arraysAreEqual(t,n){return vp(t,n)}static range(t,n,s){return Array.from({length:(n-t)/s+1},(r,c)=>t+c*s)}static sph2cartDeg(t,n){const s=-n*(Math.PI/180),r=(t-90)%360*(Math.PI/180),c=[Math.cos(s)*Math.cos(r),Math.cos(s)*Math.sin(r),Math.sin(s)],l=Math.sqrt(c[0]*c[0]+c[1]*c[1]+c[2]*c[2]);return l<=0||(c[0]/=l,c[1]/=l,c[2]/=l),c}static vox2mm(t,n){const s=re(n);We(s,s);const r=te(t[0],t[1],t[2],1);return De(r,r,s),lt(r[0],r[1],r[2])}},Ya=k,$t=class me{static readTRACT(t){const n=t.byteLength;if(n<20)throw new Error("File too small to be niml.tract: bytes = "+n);const s=new DataView(t),r=new Uint8Array(t);let c=0;function l(){for(;c1)throw new Error(`assembleDpgFromMap: multiple entries for tag "${A}" in group "${u}".`);if(g.size!==l.size)throw new Error(`assembleDpgFromMap: tag coverage mismatch for group "${u}". Expected ${l.size} tags but found ${g.size}.`);for(const A of l)if(!g.has(A))throw new Error(`assembleDpgFromMap: group "${u}" missing tag "${A}".`)}const d=[];for(const h of c){const u=[];let m=0;for(let v=0;vS.id===h);if(b.length===0)throw new Error(`assembleDpgFromMap: missing tag "${h}" for group "${y}".`);if(b.length>1)throw new Error(`assembleDpgFromMap: multiple entries for tag "${h}" in group "${y}".`);const C=b[0];if(C.vals instanceof Float32Array)u.push(C.vals),m+=C.vals.length;else try{const S=Float32Array.from(C.vals);u.push(S),m+=S.length}catch{throw new Error(`assembleDpgFromMap: invalid vals for tag "${h}" in group "${y}".`)}}const g=new Float32Array(m);let A=0;for(const v of u)g.set(v,A),A+=v.length;d.push({id:h,vals:g})}return d}static async readTRX(t){function n(w){const b=(w&31744)>>10,C=w&1023;return(w>>15?-1:1)*(b?b===31?C?NaN:1/0:Math.pow(2,b-15)*(1+C/1024):6103515625e-14*(C/1024))}let s=0,r=0,c=new Float32Array([]);const l=[],d={},h=[],u=[],m=[];let g=[],A=!1;const v=new Q2(t);for(let w=0;w0&&d&&Object.keys(d).length>0&&(y=this.assembleDpgFromMap(d,h)),l[s]=r/3,{pts:c,offsetPt0:new Uint32Array(l),dpg:y,dps:u,dpv:m,groups:h,header:g}}static readTXT(t,n=0){const r=new TextDecoder("utf-8").decode(t).split(/\r?\n|\r/).filter(l=>l.trim().length>0);n<=0&&(n=r.length);const c=new Float32Array(n);for(let l=0;l2||c!==1e3||s!==1128354388)throw new Error("Not a valid TRK file");const l=n.getInt16(36,!0),d=[];for(let V=0;V0)for(let L=0;L0)for(let R=0;R=u);b++)m[g]=parseFloat(w[b]),g++}const A=[];for(l++;r[l].length<1;)l++;if(r[l].startsWith("METADATA")){for(;r[l].length>1;)l++;l++}if(d=r[l].trim().split(/\s+/),l++,d[0].includes("LINES")){const y=parseInt(d[1]);if(y<1)throw new Error("Corrupted VTK ASCII");let w=r[l].trim();const b=[];let C=[];if(w.startsWith("OFFSETS")){l++;let S=0;for(;S=y));M++);}C=Array.from(m)}else{let S=function(){w=r[l].trim();const U=w.trim().split(/\s+/);M=[];for(let T=0;T=M.length&&S();const T=M[N++];E+=T,b[U+1]=E;for(let F=0;F=M.length&&S();const I=M[N++]*3;C.push(m[I+0]),C.push(m[I+1]),C.push(m[I+2])}}}return{pts:Float32Array.from(C),offsetPt0:Uint32Array.from(b)}}else if(d[0].includes("TRIANGLE_STRIPS")){const y=parseInt(d[1]);for(let w=0;w1&&C.pop()&&(S=S.split(".").slice(0,-1).join(".")),v==="TXT"){const T=s.offsetPt0.length-1,F=me.readTXT(n,T);if(F.length!==T)throw new Error(`TXT file has ${F.length} items, expected one per streamline (${T}).`);s.dps||(s.dps=[]);const I=F.reduce((V,R)=>Math.min(V,R)),B=F.reduce((V,R)=>Math.max(V,R));return s.dps.push({id:S,vals:Float32Array.from(F.slice()),global_min:I,global_max:B,cal_min:I,cal_max:B}),g}if(v!=="TSF")throw new Error("readLayer for streamlines only supports TSF and TXT files.");const E=s.pts.length/3,M=me.readTSF(n,E);s.dpv||(s.dpv=[]);const N=M.reduce((T,F)=>Math.min(T,F)),U=M.reduce((T,F)=>Math.max(T,F));return s.dpv.push({id:S,vals:Float32Array.from(M.slice()),global_min:N,global_max:U,cal_min:N,cal_max:U}),g}if(y<3){k.error("n_vert < 3 in layer");return}if(v==="MZ3"){const C=await me.readMZ3(n,y);g.values=C.scalars,"colormapLabel"in C&&(g.colormapLabel=C.colormapLabel)}else if(v==="ANNOT"){const C=me.readANNOT(n,y,!0);C instanceof Uint32Array?g.values=C:(g.values=C.scalars,g.colormapLabel=C.colormapLabel)}else if(v==="CRV"||v==="CURV"||v==="THICKNESS"||v==="AREA")g.values=me.readCURV(n,y),g.isTransparentBelowCalMin=!1;else if(v==="GII"){const C=await me.readGII(n,y);g.values=C.scalars,g.colormapLabel=C.colormapLabel}else if(v==="MGH"||v==="MGZ"){const C=await me.readMGH(n,y,!0);"scalars"in C?(g.values=C.scalars,g.colormapLabel=C.colormapLabel):g.values=C}else if(v==="NII")g.values=await me.readNII(n,s.pts,s.anatomicalStructurePrimary);else if(v==="SMP")g.values=await me.readSMP(n,y);else if(v==="STC")g.values=me.readSTC(n,y);else if(me.isCurv(n))g.values=me.readCURV(n,y),g.isTransparentBelowCalMin=!1;else return k.warn("Unknown layer overlay format "+t),g;if(!g.values){k.error("no values in layer");return}g.nFrame4D=g.values.length/y,g.frame4D=0,g.outlineBorder=m;let w=g.values[0],b=g.values[0];for(let C=0;C5){const g=await At.decompress(new Uint8Array(t));r=new DataView(g.buffer),c=r.getUint16(0,!0),t=g.buffer}c>5&&k.error("Unsupported or invalid BrainVoyager SMP version "+c);const l=r.getUint32(2,!0);l!==n&&k.error("SMP file has "+l+" vertices, background mesh has "+n);const d=r.getUint16(6,!0),h=new Float32Array(l*d);let u=9;function m(){const g=u;for(;u=3&&A.mapType===3&&(A.nLags=r.getUint32(u,!0),u+=4,A.mnLag=r.getUint32(u,!0),u+=4,A.mxLag=r.getUint32(u,!0),u+=4,A.ccOverlay=r.getUint32(u,!0),u+=4),A.clusterSize=r.getUint32(u,!0),u+=4,A.clusterCheck=r.getUint8(u),u+=1,A.critThresh=r.getFloat32(u,!0),u+=4,A.maxThresh=r.getFloat32(u,!0),u+=4,c>=4&&(A.includeValuesGreaterThreshMax=r.getUint32(u,!0),u+=4),A.df1=r.getUint32(u,!0),u+=4,A.df2=r.getUint32(u,!0),u+=4,c>=5?(A.posNegFlag=r.getUint32(u,!0),u+=4):A.posNegFlag=3,A.cortexBonferroni=r.getUint32(u,!0),u+=4,A.posMinRGB=[0,0,0],A.posMaxRGB=[0,0,0],A.negMinRGB=[0,0,0],A.negMaxRGB=[0,0,0],c>=2&&(A.posMinRGB[0]=r.getUint8(u),u++,A.posMinRGB[1]=r.getUint8(u),u++,A.posMinRGB[2]=r.getUint8(u),u++,A.posMaxRGB[0]=r.getUint8(u),u++,A.posMaxRGB[1]=r.getUint8(u),u++,A.posMaxRGB[2]=r.getUint8(u),u++,c>=4&&(A.negMinRGB[0]=r.getUint8(u),u++,A.negMinRGB[1]=r.getUint8(u),u++,A.negMinRGB[2]=r.getUint8(u),u++,A.negMaxRGB[0]=r.getUint8(u),u++,A.negMaxRGB[1]=r.getUint8(u),u++,A.negMaxRGB[2]=r.getUint8(u),u++),A.enableSMPColor=r.getUint8(u),u++,c>=4&&(A.lut=m()),A.colorAlpha=r.getFloat32(u,!0),u+=4),A.name=m();const v=new Float32Array(t,u,l);h.set(v,g*l),u+=l*4}return h}static readSTC(t,n){const s=new DataView(t),r=s.getInt32(8,!1);if(r!==n)throw new Error("Overlay has "+r+" vertices, expected "+n);let c=12+r*4;const l=s.getUint32(c,!1);c+=4;const d=new Float32Array(l*r);for(let h=0;h0)return h;const A=r.getInt32(d+=4,!1),v=r.getInt32(d+=4,!1);d+=v;const y=r.getInt32(d+=4,!1);if(y<1)return h;const w={R:Array(A).fill(0),G:Array(A).fill(0),B:Array(A).fill(0),A:Array(A).fill(0),I:Array(A).fill(0),labels:Array(A).fill("")};for(let E=0;E=A){k.warn("annot entry out of range");continue}w.R[M]=T,w.G[M]=F,w.B[M]=I,w.A[M]=B,w.I[M]=(B<<24)+(I<<16)+(F<<8)+T,w.labels[M]=U}const b=new Float32Array(c);b.fill(-1);let C=0;for(let E=0;E0&&k.error(`annot vertex colors do not match ${C} of ${c} vertices.`);for(let E=0;E=d*3)break;g[u+2]=parseInt(v[0])-1,g[u+1]=parseInt(v[1])-1,g[u+0]=parseInt(v[2])-1,u+=3}return{positions:m,indices:g}}static readASC(t){const n=t.byteLength,s=new Uint8Array(t);let r=0;function c(){for(;r=2147483648||M)throw new Error("values exceed 2GB limit");const N=c();if(!N.startsWith("CONNECTIVITY"))throw new Error("Expected CONNECTIVITY after OFFSETS");S=N.includes("int64");const U=E[w-1],T=new Uint32Array(U);for(let F=0;F65535)throw new Error("Invalid VTK binary polygons using little-endian data (MRtrix)");r+=4;const M=A.getInt32(r,!1);r+=4;let N=A.getInt32(r,!1);r+=4;for(let U=0;UA!==-1));return{positions:u,indices:g,colors:m}}static readDFS(t){const n=new DataView(t),s=n.getUint32(0,!0),r=n.getUint16(4,!0);(s!==1599292996||r!==17740)&&k.warn("Not a little-endian brainsuite DFS mesh");const c=n.getUint32(12,!0),l=n.getUint32(24,!0),d=n.getUint32(28,!0),h=n.getUint32(48,!0);let u=c;const m=new Uint32Array(t,u,l*3);u+=l*3*4;const g=new Float32Array(t,u,d*3);for(let v=0;v=0&&(A=new Float32Array(t,h,d*3)),{positions:g,indices:m,colors:A}}static async readMZ3(t,n=0){if(t.byteLength<20)throw new Error("File too small to be mz3: bytes = "+t.byteLength);let s=new DataView(t),r=t,c=s.getUint16(0,!0);if(c===35615||c===8075){const I=await At.decompress(new Uint8Array(t));s=new DataView(I.buffer),c=s.getUint16(0,!0),r=I.buffer}const l=s.getUint16(2,!0),d=s.getUint32(4,!0);let h=s.getUint32(8,!0);const u=s.getUint32(12,!0);if(Ya.debug("MZ3 magic %d attr %d face %d vert %d skip %d",c,l,d,h,u),c!==23117)throw new Error("Invalid MZ3 file");const m=(l&1)!==0,g=(l&2)!==0,A=(l&4)!==0;let v=(l&8)!==0;const y=(l&16)!==0,w=(l&32)!==0,b=(l&64)!==0;if(Ya.debug(`isFace=${m} isVert=${g} isRGBA=${A} isSCALAR=${v} isDOUBLE=${y} isAOMAP=${w} isLOOKUP=${b}`),l>127)throw new Error("Unsupported future version of MZ3 file");let C=4;y&&(C=8);let S=0;if(n>0&&!m&&d<1&&!A&&(v=!0),v){const I=n||h,B=16+u+(m?d*12:0)+(g?I*12:0)+(A?I*4:0),V=Math.floor((r.byteLength-B)/C);h!==n&&V%n===0&&(h=n),S=Math.floor(V/h),S<1&&(k.warn("Corrupt MZ3: file reports NSCALAR but not enough bytes"),v=!1)}if(h<3&&n<3)throw new Error("Not a mesh MZ3 file (maybe scalar)");n>0&&n!==h&&k.warn("Layer has "+h+"vertices, but background mesh has "+n);let E=16+u;const M=new DataView(r);let N=null;if(m){N=new Uint32Array(d*3);for(let I=0;I0)if(y){const I=new Float64Array(S*h);for(let B=0;B0&&b&&v){const I=new TextDecoder("utf-8"),B=new Uint8Array(r,16,u),V=I.decode(B),R=JSON.parse(V),Y=Pt.makeLabelLut(R);return{scalars:F,colormapLabel:Y}}if(n>0&&A&&v){let I=F[0];for(let R=0;R0?{scalars:F}:{positions:U,indices:N,scalars:F,colors:T}}static readPLY(t){const n=t.byteLength,s=new Uint8Array(t);let r=0;function c(){for(;rB.length){const H=new Uint32Array(B.length+B.length);H.set(B),B=H.slice()}const X=parseInt(Y[C+1]);let L=parseInt(Y[C+2]);for(let H=0;H1&&k.warn("This is not a valid FreeSurfer ICO/TRI mesh.");const l=parseInt(c[0]),d=new Float32Array(l*3);let h=1;for(let g=0;g=l){k.error("ICO vertices corrupted");break}v*=3,d[v]=y,d[v+1]=w,d[v+2]=b}c=r[h].trim().split(/\s+/),h++;const u=parseInt(c[0]),m=new Uint32Array(u*3);for(let g=0;g=u){k.error("ICO indices corrupted");break}v*=3,m[v]=y,m[v+1]=w,m[v+2]=b}for(let g=0;g1||m!==u*3)&&k.warn("Multi-part BYU/GEO header or not a triangular mesh.");const g=[];h*=3;let A=0,v=2;for(;A=h));E++);}const y=[];u*=3;let w=0;for(;w=u));E++);}if(n)for(let S=0;S2)&&k.warn("This is not a valid MNI OBJ mesh.");let g=1;m===1?g=u:m===1&&(g=l),c+=g*4,c+=u;const A=u*3,v=new Uint32Array(A);for(let y=0;yA&&(A=m[v]);if(A-g+1>u.length/3)throw new Error("Not a valid OBJ file");for(let v=0;v1056964608&&(E[A+0]=(T>>16&255)/255,E[A+1]=(T>>8&255)/255,E[A+2]=(T&255)/255),T===0&&(E[A+0]=v,E[A+1]=y,E[A+2]=w),T===1&&(E[A+0]=b,E[A+1]=C,E[A+2]=S),A+=3}g+=c*4;for(let U=0;U=3e3&&A<=3099&&u>580){let b=function(){for(;I"))return L;for(;I");)L+=b();return L},S=function(L,H=!1){const W=B.indexOf(L);if(W<0)return 1;const at=B.indexOf('"',W)+1,ct=B.indexOf('"',at),G=B.slice(at,ct);return H?G:parseInt(G)},E=0,M=0,N=0,U="",T=new Uint32Array;const F=new Uint8Array(t);let I=552,B;const V=w[5],R=new Float32Array(n*V);for(;I"));)if(B.includes("")||(B=C()),!B.startsWith("")||!B.endsWith(""))return k.warn("Unable to find CIfTI "),R;B=B.slice(15,-16);const at=B.trim().split(/\s+/);at.length=3&&C[1]>1&&C[2]>1&&C[3]>1)S=!0,E=C[1]*C[2]*C[3];else throw new Error("Voxels in layer ("+b+") is not a multiple of number of vertices ("+r+")");if(b=E,l)y===16?c=new Float32Array(t,u,b):y===8?c=new Int32Array(t,u,b):y===4&&(c=new Int16Array(t,u,b));else if(y===16){c=new Float32Array(b);for(let M=0;Mv||v<=0)&&k.warn(`Requires valid sform (sform_code = ${v})`);const U=Ut();Pe(U,w);const T=C[1],F=C[2],I=C[3],B=T*F;let V=0,R=0,Y=0;for(;R=T||W<0||G>=F||at<0||j>=I)continue;const $=H+W*T+at*B,et=new Float32Array(8);et[0]=c[$],et[1]=c[$+1],et[2]=c[$+T],et[3]=c[$+T+1],et[4]=c[$+B],et[5]=c[$+B+1],et[6]=c[$+B+T],et[7]=c[$+B+T+1];let ot=et[0],mt=ot;for(let vt=1;vt<8;vt++)ot=Math.max(ot,et[vt]),mt=Math.min(mt,et[vt]);Math.abs(mt)>ot&&(ot=mt),N[R-1]=ot,Y++}const P=Y/r;P<.1&&k.warn(`${Y} of ${r} vertices in range (${(P*100).toFixed(1)}%)`),c=N}return c}static async readMGH(t,n=0,s=!1){let r=new DataView(t),c=t;if(r.getUint8(0)===31&&r.getUint8(1)===139){const T=await At.decompress(new Uint8Array(t));c=new ArrayBuffer(T.byteLength),new Uint8Array(c).set(new Uint8Array(T)),r=new DataView(T.buffer)}const l=r.getInt32(0,!1),d=Math.max(1,r.getInt32(4,!1)),h=Math.max(1,r.getInt32(8,!1)),u=Math.max(1,r.getInt32(12,!1)),m=Math.max(1,r.getInt32(16,!1)),g=r.getInt32(20,!1);let A=284;const v=!1;(l!==1||g<0||g>4)&&k.warn("Not a valid MGH file");let y=d*h*u*m,w=[];if(y=this.decimateLayerVertices(y,n),y%n!==0)return k.warn("Vertices in layer ("+y+") is not a multiple of number of vertices ("+n+")"),w;if(g===3){w=new Float32Array(y);for(let T=0;T0)return k.warn("unsupported CTABreadFromBinaryV1"),w;if(I=-I,I!==2)return k.warn("CTABreadFromBinary: unknown version"),w;const B=r.getInt32(A+=4,v);if(B<0)return k.warn("CTABreadFromBinaryV2: nentries was ",B),w;const V=r.getInt32(A+=4,v);A+=V;const R=r.getInt32(A+=4,v);if(R<0)return w;const Y={R:[],G:[],B:[],A:[],I:[],labels:[]};for(let P=0;P"))if(l.startsWith(""))for(;r");)l+=c();else for(;r");)l+=c();const E=d("USE");if(E.length>1){E in C?w=C[E]:k.warn("Unable to find DEF for "+E);return}const M=h("diffuseColor");if(M.length<3)return;w[0]=Math.round(M[0]*255),w[1]=Math.round(M[1]*255),w[2]=Math.round(M[2]*255);const N=d("DEF");N.length<1||(C[N]=w)}for(;r=0?(m.push(N[V]+T),m.push(N[F-1]+T),m.push(N[F-0]+T),F+=1):(F+=3,V=F-2)}else for(;F=0?(m.push(N[F-2]+T),m.push(N[F-1]+T),m.push(N[F-0]+T),F+=1):F+=3;u=[...u,...U];const I=Math.floor(U.length/3),B=Array(I).fill(w).flat();if(A.length===I*3){let V=0,R=0;for(let Y=0;Y";)c++;if(R=r[c-1]==="/",Y+1=s)break}const P=new TextDecoder().decode(t.slice(Y+1,c)).trim(),X=P.split(" ")[0].trim(),L=c;let H=c,W=c;if(r[Y+1]!=="?"&&r[Y+1]!=="!"){const at="";H=r.indexOf(at,L),W=H+at.length-1}return{name:P,startPos:Y,contentStartPos:L,contentEndPos:H,endPos:W}}let d=l();if(!d.name.startsWith("?xml"))throw new Error("readGII: Invalid XML file");for(;!d.name.startsWith("GIFTI")&&d.endPos1;){if(d=l(),d.name.startsWith("Label Key")&&(T=d.name,B.I.push(F("Key=")),B.R.push(Math.round(255*F("Red=",!0))),B.G.push(Math.round(255*F("Green=",!0))),B.B.push(Math.round(255*F("Blue=",!0))),B.A.push(Math.round(255*F("Alpha",!0))),T=new TextDecoder().decode(t.slice(d.contentStartPos+1,d.contentEndPos)).trim(),B.labels.push(I(""u"){let Y=function(P){const X=atob(P),L=X.length,H=new Uint8Array(L);for(let W=0;W1&&(B.A.some(Y=>Y>0)||B.A.fill(255),V=Pt.makeLabelLut(B)),n>0)return{scalars:m,colormapLabel:V,anatomicalStructurePrimary:g};if(h.length>2&&!U&&(C[0]!==0||C[1]!==0||C[2]!==0)){N=Math.floor(h.length/3);let R=0;for(let Y=0;Y{const i=new ArrayBuffer(2);return new DataView(i).setInt16(0,256,!0),new Int16Array(i)[0]===256},Z2=(i=>(i[i.UNKNOWN=0]="UNKNOWN",i[i.NII=1]="NII",i[i.DCM=2]="DCM",i[i.DCM_MANIFEST=3]="DCM_MANIFEST",i[i.MIH=4]="MIH",i[i.MIF=5]="MIF",i[i.NHDR=6]="NHDR",i[i.NRRD=7]="NRRD",i[i.MHD=8]="MHD",i[i.MHA=9]="MHA",i[i.MGH=10]="MGH",i[i.MGZ=11]="MGZ",i[i.V=12]="V",i[i.V16=13]="V16",i[i.VMR=14]="VMR",i[i.HEAD=15]="HEAD",i[i.DCM_FOLDER=16]="DCM_FOLDER",i[i.SRC=17]="SRC",i[i.FIB=18]="FIB",i[i.BMP=19]="BMP",i[i.ZARR=20]="ZARR",i[i.NPY=21]="NPY",i[i.NPZ=22]="NPZ",i[i.HDR=23]="HDR",i))(Z2||{}),bt=Object.freeze({...Z2,parse:i=>{let t=0;switch(i.toUpperCase()){case"":case"DCM":t=2;break;case"TXT":t=3;break;case"FZ":case"GQI":case"QSDR":case"FIB":t=18;break;case"HDR":case"NII":t=1;break;case"MIH":t=4;break;case"MIF":t=5;break;case"NHDR":t=6;break;case"NRRD":t=7;break;case"MHD":t=8;break;case"MHA":t=9;break;case"MGH":t=10;break;case"MGZ":t=11;break;case"NPY":t=21;break;case"NPZ":t=22;break;case"SRC":t=17;break;case"V":t=12;break;case"V16":t=13;break;case"VMR":t=14;break;case"HEAD":t=15;break;case"PNG":case"BMP":case"GIF":case"JPG":case"JPEG":t=19;break;case"ZARR":t=20;break}return t}}),Gl=(i,t="",n="",s="gray",r=1,c=NaN,l=NaN,d=!0,h=.02,u=!1,m=!1,g="",A=0,v=bt.UNKNOWN,y=NaN,w=NaN,b=!0,C=!1,S=null)=>({url:i,urlImageData:t,name:n,colormap:s,colorMap:s,opacity:r,cal_min:c,cal_max:l,trustCalMinMax:d,percentileFrac:h,ignoreZeroVoxels:u,useQFormNotSForm:m,colormapNegative:g,imageType:v,cal_minNeg:y,cal_maxNeg:w,colorbarVisible:b,frame4D:A,alphaThreshold:C,colormapLabel:S});function i2(i,t=80){i=i.replace(/[`$]/g,"");const n=[],s=Math.min(t,i.length);for(let r=0;r=d)break;let A=!0;for(let v=0;v<3;++v)r[v]>s[v]&&(A=!1),c[v]0,c=new Uint8Array(4);c[0]=r?1:0;let l=new Uint8Array(0);if(r){const b=[];let C=0;for(const E of i.extensions){const M=new Uint8Array(E.edata),N=new Uint8Array(8+M.length),U=new DataView(N.buffer);U.setInt32(0,E.esize,!0),U.setInt32(4,E.ecode,!0),N.set(M,8),b.push(N),C+=N.length}l=new Uint8Array(C);let S=0;for(const E of b)l.set(E,S),S+=E.length}const d=348;s.vox_offset=Math.max(352,d+c.length+l.length),n&&(s.datatypeCode=2,s.numBitsPerVoxel=8,s.scl_slope=1,s.scl_inter=0);const h=Kl(s,n);let u;if(n){const b=t,C=i.permRAS;if(C&&(C[0]!==1||C[1]!==2||C[2]!==3)){k.debug("Reorienting drawing bytes back to native space for saving...");const S=i.hdr.dims,E=S[1]*S[2]*S[3],M=i.dimsRAS?i.dimsRAS[1]*i.dimsRAS[2]*i.dimsRAS[3]:E;if(b.length!==M)console.warn(`Drawing length (${b.length}) does not match expected RAS voxel count (${M}). Cannot reorient drawing reliably.`),u=b;else if(!i.img2RASstep||!i.img2RASstart||!i.dimsRAS)console.warn("Missing RAS transformation info (img2RASstep, img2RASstart, dimsRAS). Cannot reorient drawing reliably."),u=b;else{const N=i.img2RASstep,U=i.img2RASstart,T=i.dimsRAS,F=new Uint8Array(E);F.fill(0);const I=b;let B=0;for(let V=0;V=0&&HURL.revokeObjectURL(c),100)}catch(r){k.error("Failed to trigger download:",r)}return s}function $2(i,t,n,s,r=0,c=!1){if(!i.hdr)throw new Error("getValue: NVImage header is not defined.");if(!c&&!i.img)throw new Error("getValue: NVImage image data is not defined.");if(c&&!i.imaginary)return k.warn("getValue: Attempted to read imaginary data, but none exists."),[0];const l=i.hdr.dims[1],d=i.hdr.dims[2],h=i.hdr.dims[3],u=i.permRAS.slice();if(u[0]!==1||u[1]!==2||u[2]!==3){const S=te(t,n,s,1);De(S,S,i.toRASvox),t=S[0],n=S[1],s=S[2]}t=Math.max(0,Math.min(Math.round(t),l-1)),n=Math.max(0,Math.min(Math.round(n),d-1)),s=Math.max(0,Math.min(Math.round(s),h-1)),r=Math.max(0,r);let m=t+n*l+s*l*d;if(i.hdr.datatypeCode===2304)return i.img?(m*=4,m+3>=i.img.length?(k.warn(`getValue: Calculated index ${m} out of bounds for RGBA data.`),[0]):[i.img[m],i.img[m+1],i.img[m+2],i.img[m+3]]):[0];if(i.hdr.datatypeCode===128)return i.img?(m*=3,m+2>=i.img.length?(k.warn(`getValue: Calculated index ${m} out of bounds for RGB data.`),[0]):[i.img[m],i.img[m+1],i.img[m+2]]):[0];const g=l*d*h,A=r*g,v=m+A,y=c?i.imaginary:i.img;if(v<0||v>=y.length)return[0];const w=y[v],b=isNaN(i.hdr.scl_slope)||i.hdr.scl_slope===0?1:i.hdr.scl_slope,C=isNaN(i.hdr.scl_inter)?0:i.hdr.scl_inter;return[b*w+C]}function m4(i,t,n,s,r=0,c=!1){const l=$2(i,t,n,s,r,c);return l.length<3?l[0]:l[0]*.2126+l[1]*.7152+l[2]*.0722}function g4(i,t=[-1,0,0],n=[0,0,0],s="same"){const r=[new Uint8Array,[0,0,0]];if(!i.hdr||!i.img||!i.dimsRAS||!i.img2RASstep||!i.img2RASstart)return k.error("getVolumeData: Missing required NVImage properties (hdr, img, dimsRAS, img2RASstep/start)."),r;if(t=t.slice(0,3),n=n.slice(0,3),Math.min(...t)<0||Math.min(...n)<0)return k.warn("getVolumeData: Invalid start or end coordinates provided."),r;const c=i.dimsRAS.slice(1,4);for(let b=0;b<3;b++)if(t[b]=Math.max(0,Math.min(Math.round(t[b]),c[b]-1)),n[b]=Math.max(0,Math.min(Math.round(n[b]),c[b]-1)),n[b]=0&&U=0&&Cim,optimizeFreeSurferLabels:()=>em,readMgh:()=>p4});function s2(i,t,n,s=1){const r=t+n;let c=t;const l=[];for(;c+12<=r;){const d=i.getInt32(c,!1),h=i.getInt32(c+8,!1);if(c+=12,h<=0||c+h>r)break;if(d!==s){c+=h;continue}let u=h,m=c;if(s===1){if(c+4>r)break;u=i.getInt32(c,!1),m+=4}if(u>1&&m+u<=r){const g=new Uint8Array(i.buffer,m,u),A=new TextDecoder("utf-8").decode(g.slice(0,-1));l.push(A)}c+=h}return l.join(` + +`)}function em(i,t){if(i.intent_code=1002,i.datatypeCode!==16&&i.datatypeCode!==8)return t;let n=new Float32Array(t);if(i.datatypeCode===8&&(n=new Int32Array(t)),Zh()){const l=new Uint32Array(t);for(let d=0;d>>8|(h&4278190080)>>>24}}i.littleEndian=Zh();let s=!0,r=1/0,c=-1/0;for(let l=0;lc&&(c=d))}if(!s||r<0||c>2147483647)return k.warn(`FreeSurfer Labels must be integers in INT32 range. range ${r}..${c}`),t;if(c>32767){i.datatypeCode=8;const l=new Int32Array(n.length);for(let d=0;d255){i.datatypeCode=4,i.numBitsPerVoxel=16;const l=new Int16Array(n.length);for(let d=0;d=2&&r.getUint8(0)===31&&r.getUint8(1)===139)try{s=await At.decompressToBuffer(new Uint8Array(t)),r=new DataView(s)}catch(H){return k.error("Failed to decompress MGZ file.",H),null}if(s.byteLength<284)return k.error("File too small to be a valid MGH/MGZ header."),null;const c=r.getInt32(0,!1),l=r.getInt32(4,!1),d=r.getInt32(8,!1),h=r.getInt32(12,!1),u=r.getInt32(16,!1),m=r.getInt32(20,!1),g=r.getFloat32(30,!1),A=r.getFloat32(34,!1),v=r.getFloat32(38,!1),y=r.getFloat32(42,!1),w=r.getFloat32(46,!1),b=r.getFloat32(50,!1),C=r.getFloat32(54,!1),S=r.getFloat32(58,!1),E=r.getFloat32(62,!1),M=r.getFloat32(66,!1),N=r.getFloat32(70,!1),U=r.getFloat32(74,!1),T=r.getFloat32(78,!1),F=r.getFloat32(82,!1),I=r.getFloat32(86,!1);if(c!==1&&k.warn(`Unexpected MGH version: ${c}.`),l<=0||d<=0||h<=0)return k.error(`Invalid MGH dimensions: ${l}x${d}x${h}`),null;switch(m){case 0:n.numBitsPerVoxel=8,n.datatypeCode=2;break;case 4:n.numBitsPerVoxel=16,n.datatypeCode=4;break;case 1:n.numBitsPerVoxel=32,n.datatypeCode=8;break;case 3:n.numBitsPerVoxel=32,n.datatypeCode=16;break;default:return k.error(`Unsupported MGH data type: ${m}`),null}n.dims[1]=l,n.dims[2]=d,n.dims[3]=h,n.dims[4]=Math.max(1,u),n.dims[0]=n.dims[4]>1?4:3,n.pixDims[1]=Math.abs(g),n.pixDims[2]=Math.abs(A),n.pixDims[3]=Math.abs(v),n.pixDims[4]=0,n.sform_code=1,n.qform_code=0,n.sform_code=1;const B=oi(y*n.pixDims[1],C*n.pixDims[2],M*n.pixDims[3],0,w*n.pixDims[1],S*n.pixDims[2],N*n.pixDims[3],0,b*n.pixDims[1],E*n.pixDims[2],U*n.pixDims[3],0,0,0,0,1),V=[n.dims[1]/2,n.dims[2]/2,n.dims[3]/2,1],R=[0,0,0,0];for(let H=0;H<3;H++){R[H]=0;for(let W=0;W<3;W++)R[H]=R[H]+B[W+H*4]*V[W]}n.affine=[[B[0],B[1],B[2],T-R[0]],[B[4],B[5],B[6],F-R[1]],[B[8],B[9],B[10],I-R[2]],[0,0,0,1]],n.vox_offset=284,n.magic="n+1";const Y=n.numBitsPerVoxel/8,X=l*d*h*n.dims[4]*Y,L=s.slice(n.vox_offset,n.vox_offset+X);return im(s,n,X)?em(n,L):L}var nm={};_l(nm,{readNifti:()=>v4});async function v4(i,t,n){let s=t,r=null;try{if(su(s)&&(k.debug(`Decompressing NIfTI file: ${i.name}`),s=await Kp(s),k.debug(`Decompression complete for: ${i.name}`)),!s||s.byteLength===0)throw new Error("Buffer became invalid after decompression attempt.");if(i.hdr=await Ka(s,n!=null),Qp(i.hdr)&&(i.extensions=i.hdr.extensions),i.hdr===null)throw new Error(`Failed to read NIfTI header: ${i.name}`);if(i.hdr.cal_min===0&&i.hdr.cal_max===255&&i.hdr.datatypeCode!==2&&(k.debug(`Resetting suspicious cal_min/max (0/255) for non-uint8 NIfTI: ${i.name}`),i.hdr.cal_min=0,i.hdr.cal_max=0),r=n?Yd(i.hdr,n):Yd(i.hdr,s),r===null)throw new Error(`nifti-reader-js readImage returned null for ${i.name}`);return r}catch(c){return k.error(`Error processing NIfTI file ${i.name}:`,c),i.hdr=null,null}}var sm={};_l(sm,{readNrrd:()=>x4});async function x4(i,t,n=null){i.hdr||(k.warn("readNrrd called before nvImage.hdr was initialized. Creating default."),i.hdr=new ut);const s=i.hdr;s.pixDims=[1,1,1,1,1,0,0,0];const r=t.byteLength;let c=null;const l=new Uint8Array(t);for(let U=1;U=b.byteLength)return k.error(`NRRD data offset (${C}) invalid for buffer length (${b?.byteLength??0})`),null;let S=b.slice(C);if(u)try{k.debug("Decompressing NRRD data..."),S=await At.decompressToBuffer(new Uint8Array(S)),k.debug("Decompression complete.")}catch(U){return k.error("Failed to decompress NRRD data.",U),null}const E=s.numBitsPerVoxel/8,N=s.dims.slice(1,s.dims[0]+1).reduce((U,T)=>U*Math.max(1,T),1)*E;return S.byteLengthN&&(k.warn(`NRRD has extra ${S.byteLength-N} bytes after expected image data. Truncating.`),S=S.slice(0,N)),w=S,s.datatypeCode?s.numBitsPerVoxel?w:(k.error("NRRD parsing failed to set numBitsPerVoxel."),null):(k.error("NRRD parsing failed to set datatypeCode."),null))}var Ue=class Hl{constructor(t=null,n="",s="gray",r=1,c=null,l=NaN,d=NaN,h=!0,u=.02,m=!1,g=!1,A="",v=0,y=bt.UNKNOWN,w=NaN,b=NaN,C=!0,S=null,E=0){z(this,"name"),z(this,"id"),z(this,"url"),z(this,"headers"),z(this,"_colormap"),z(this,"_opacity"),z(this,"percentileFrac"),z(this,"ignoreZeroVoxels"),z(this,"trustCalMinMax"),z(this,"colormapNegative"),z(this,"colormapLabel"),z(this,"colormapInvert"),z(this,"nFrame4D"),z(this,"frame4D"),z(this,"nTotalFrame4D"),z(this,"cal_minNeg"),z(this,"cal_maxNeg"),z(this,"colorbarVisible",!0),z(this,"modulationImage",null),z(this,"modulateAlpha",0),z(this,"series",[]),z(this,"nVox3D"),z(this,"oblique_angle"),z(this,"maxShearDeg"),z(this,"useQFormNotSForm"),z(this,"colormapType"),z(this,"pixDims"),z(this,"matRAS"),z(this,"pixDimsRAS"),z(this,"obliqueRAS"),z(this,"dimsRAS"),z(this,"permRAS"),z(this,"img2RASstep"),z(this,"img2RASstart"),z(this,"toRAS"),z(this,"toRASvox"),z(this,"frac2mm"),z(this,"frac2mmOrtho"),z(this,"extentsMinOrtho"),z(this,"extentsMaxOrtho"),z(this,"mm2ortho"),z(this,"hdr",null),z(this,"extensions"),z(this,"imageType"),z(this,"img"),z(this,"imaginary"),z(this,"v1"),z(this,"fileObject"),z(this,"dims"),z(this,"onColormapChange",()=>{}),z(this,"onOpacityChange",()=>{}),z(this,"mm000"),z(this,"mm100"),z(this,"mm010"),z(this,"mm001"),z(this,"cal_min"),z(this,"cal_max"),z(this,"robust_min"),z(this,"robust_max"),z(this,"global_min"),z(this,"global_max"),z(this,"urlImgData"),z(this,"isManifest"),z(this,"limitFrames4D"),this.init(t,n,s,r,c,l,d,h,u,m,g,A,v,y,w,b,C,S,E)}init(t=null,n="",s="",r=1,c=null,l=NaN,d=NaN,h=!0,u=.02,m=!1,g=!1,A="",v=0,y=bt.UNKNOWN,w=NaN,b=NaN,C=!0,S=null,E=0,M=null){const N=s==="";if(N&&(s="gray"),this.name=n,this.imageType=y,this.id=qh(),this._colormap=s,this._opacity=r>1?1:r,this.percentileFrac=u,this.ignoreZeroVoxels=m,this.trustCalMinMax=h,this.colormapNegative=A,this.colormapLabel=S,this.frame4D=v,this.cal_minNeg=w,this.cal_maxNeg=b,this.colorbarVisible=C,this.colormapType=E,this.useQFormNotSForm=g,!t)return;if(N&&this.hdr&&this.hdr.intent_code===1002&&(s="random",this._colormap=s),this.hdr&&typeof this.hdr.magic=="number"&&(this.hdr.magic="n+1"),this.nFrame4D=1,this.hdr)for(let I=4;I<7;I++)this.hdr.dims[I]>1&&(this.nFrame4D*=this.hdr.dims[I]);if(this.frame4D=Math.min(this.frame4D,this.nFrame4D-1),this.nTotalFrame4D=this.nFrame4D,!this.hdr||!M)return;this.nVox3D=this.hdr.dims[1]*this.hdr.dims[2]*this.hdr.dims[3];const U=this.nVox3D*(this.hdr.numBitsPerVoxel/8),T=M.byteLength/U;T!==this.nFrame4D&&(T>0&&T*U===M.byteLength?k.debug("Loading the first "+T+" of "+this.nFrame4D+" volumes"):k.warn("This header does not match voxel data",this.hdr,M.byteLength),this.nFrame4D=T),(this.hdr.intent_code===1007||this.hdr.intent_code===2003)&&this.nFrame4D===3&&this.hdr.datatypeCode===16&&(M=this.float32V1asRGBA(new Float32Array(M)).buffer),(this.hdr.pixDims[1]===0||this.hdr.pixDims[2]===0||this.hdr.pixDims[3]===0)&&k.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 F=n2(this.hdr.affine);if(g||!F||this.hdr.qform_code>this.hdr.sform_code){k.debug("spatial transform based on QForm");const I=this.hdr.quatern_b,B=this.hdr.quatern_c,V=this.hdr.quatern_d,R=Math.sqrt(1-(Math.pow(I,2)+Math.pow(B,2)+Math.pow(V,2))),Y=this.hdr.pixDims[0]===0?1:this.hdr.pixDims[0],P=[[R*R+I*I-B*B-V*V,2*I*B-2*R*V,2*I*V+2*R*B],[2*I*B+2*R*V,R*R+B*B-I*I-V*V,2*B*V-2*R*I],[2*I*V-2*R*B,2*B*V+2*R*I,R*R+V*V-B*B-I*I]],X=this.hdr.affine;for(let L=0;L<3;L+=1)for(let H=0;H<3;H+=1)X[L][H]=P[L][H]*this.hdr.pixDims[H+1],H===2&&(X[L][H]*=Y);X[0][3]=this.hdr.qoffset_x,X[1][3]=this.hdr.qoffset_y,X[2][3]=this.hdr.qoffset_z,this.hdr.affine=X}if(F=n2(this.hdr.affine),!F){k.debug("Defective NIfTI: spatial transform does not make sense");let I=this.hdr.pixDims[1],B=this.hdr.pixDims[2],V=this.hdr.pixDims[3];(isNaN(I)||I===0)&&(I=1),(isNaN(B)||B===0)&&(B=1),(isNaN(V)||V===0)&&(V=1),this.hdr.pixDims[1]=I,this.hdr.pixDims[2]=B,this.hdr.pixDims[3]=V;const R=[[I,0,0,0],[0,B,0,0],[0,0,V,0],[0,0,0,1]];this.hdr.affine=R}if(this.hdr.datatypeCode!==128&&this.hdr.datatypeCode!==2304&&this.hdr.littleEndian!==Zh()&&this.hdr.numBitsPerVoxel>8){if(this.hdr.numBitsPerVoxel===16){const I=new Uint16Array(M);for(let B=0;B>8&255)<<16>>16}}else if(this.hdr.numBitsPerVoxel===32){const I=new Uint32Array(M);for(let B=0;B>8&65280|V>>24&255}}else if(this.hdr.numBitsPerVoxel===64){const I=this.hdr.numBitsPerVoxel/8,B=new Uint8Array(M);for(let V=0;V=2&&y===bt.DCM){const I=new Uint8Array(t);(I[0]===92&&I[1]===1||I[1]===92&&I[0]===1)&&(y=bt.NII)}switch(N.imageType=y,y){case bt.DCM_FOLDER:case bt.DCM_MANIFEST:case bt.DCM:return;case bt.FIB:[F,N.v1]=await N.readFIB(t);break;case bt.MIH:case bt.MIF:F=await N.readMIF(t,c);break;case bt.NHDR:case bt.NRRD:if(F=await sm.readNrrd(N,t),F===null)throw new Error(`Failed to parse NHDR/NRRD file ${n}`);break;case bt.MHD:case bt.MHA:F=await N.readMHA(t,c);break;case bt.MGH:case bt.MGZ:if(F=await tm.readMgh(N,t),F===null)throw new Error(`Failed to parse MGH/MGZ file ${n}`);break;case bt.SRC:F=await N.readSRC(t);break;case bt.V:F=N.readECAT(t);break;case bt.V16:F=N.readV16(t);break;case bt.VMR:F=N.readVMR(t);break;case bt.HEAD:F=await N.readHEAD(t,c);break;case bt.BMP:F=await N.readBMP(t);break;case bt.NPY:F=await N.readNPY(t);break;case bt.NPZ:F=await N.readNPZ(t);break;case bt.ZARR:F=await N.readZARR(t,M);break;case bt.NII:if(F=await nm.readNifti(N,t,c),F===null)throw new Error(`Failed to parse NIfTI file ${n}.`);break;default:throw new Error("Image type not supported")}return N.init(t,n,s,r,c,l,d,h,u,m,g,A,v,y,w,b,C,S,E,F),N}computeObliqueAngle(t){const n=re(t);We(n,t);const s=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]),r=Math.max(Math.max(Math.abs(n[0]),Math.abs(n[1])),Math.abs(n[2]))/s,c=Math.sqrt(n[4]*n[4]+n[5]*n[5]+n[6]*n[6]),l=Math.max(Math.max(Math.abs(n[4]),Math.abs(n[5])),Math.abs(n[6]))/c,d=Math.sqrt(n[8]*n[8]+n[9]*n[9]+n[10]*n[10]),h=Math.max(Math.max(Math.abs(n[8]),Math.abs(n[9])),Math.abs(n[10]))/d,u=Math.min(Math.min(r,l),h);let m=Math.abs(Math.acos(u)*180/3.141592653);return m>.01?k.warn("Warning voxels not aligned with world space: "+m+` degrees from plumb. +`):m=0,m}float32V1asRGBA(t){t.length!==this.nVox3D*3&&k.warn("float32V1asRGBA() expects "+this.nVox3D*3+"voxels, got ",+t.length);const n=t.slice();this.hdr.datatypeCode=2304,this.nFrame4D=1;for(let h=4;h<7;h++)this.hdr.dims[h]=1;this.hdr.dims[0]=3;const s=new Uint8Array(this.nVox3D*4);let r=1;for(let h=0;h0)*1,v=+(m>0)*2,y=+(g>0)*4;let w=248+A+v+y;Math.abs(u)+Math.abs(m)+Math.abs(g)<.1&&(w=0),s[d+3]=w,d+=4}return s}loadImgV1(t=!1,n=!1,s=!1){let r=this.v1;if(!r&&this.nFrame4D===3&&this.img.constructor===Float32Array&&(r=this.img.slice()),!r)return k.warn("Image does not have V1 data"),!1;if(t)for(let c=0;c.1&&k.warn("Warning: voxels are rhomboidal, maximum shear is %f degrees.",this.maxShearDeg);const u=te(this.dimsRAS[1],this.dimsRAS[2],this.dimsRAS[3],1),m=re(this.matRAS);We(m,m);const g=te(-.5,-.5,-.5,0);Ps(m,m,lt(g[0],g[1],g[2])),m[0]*=u[0],m[1]*=u[0],m[2]*=u[0],m[4]*=u[1],m[5]*=u[1],m[6]*=u[1],m[8]*=u[2],m[9]*=u[2],m[10]*=u[2],this.frac2mm=re(m);const A=this.pixDimsRAS[1],v=this.pixDimsRAS[2],y=this.pixDimsRAS[3],w=re(m);w[0]=A*u[0],w[1]=0,w[2]=0,w[4]=0,w[5]=v*u[1],w[6]=0,w[8]=0,w[9]=0,w[10]=y*u[2];const b=this.mm2vox([0,0,0],!0);w[12]=(-b[0]-.5)*A,w[13]=(-b[1]-.5)*v,w[14]=(-b[2]-.5)*y,this.frac2mmOrtho=re(w),this.extentsMinOrtho=[w[12],w[13],w[14]],this.extentsMaxOrtho=[w[0]+w[12],w[5]+w[13],w[10]+w[14]],this.mm2ortho=Ut(),Pe(this.mm2ortho,c)}THD_daxes_to_NIFTI(t,n,s){const r=this.hdr;if(r===null)throw new Error("HDR is not set");r.sform_code=2;const c="xxyyzzg";let l=-1,d=-1,h=-1;const u=["x","y","z"];u[0]=c[s[0]],u[1]=c[s[1]],u[2]=c[s[2]];const m=t.slice(0,3),g=n.slice(0,3);for(let A=0;A<3;A++)u[A]==="x"?l=A:u[A]==="y"?d=A:h=A;l<0||d<0||h<0||l===d||l===h||d===h||(r.pixDims[1]=Math.abs(m[0]),r.pixDims[2]=Math.abs(m[1]),r.pixDims[3]=Math.abs(m[2]),r.affine=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],r.affine[0][l]=-m[l],r.affine[1][d]=-m[d],r.affine[2][h]=m[h],r.affine[0][3]=-g[l],r.affine[1][3]=-g[d],r.affine[2][3]=g[h])}SetPixDimFromSForm(){if(!this.hdr)throw new Error("hdr not defined");const t=this.hdr.affine,n=oi(t[0][0],t[0][1],t[0][2],t[0][3],t[1][0],t[1][1],t[1][2],t[1][3],t[2][0],t[2][1],t[2][2],t[2][3],t[3][0],t[3][1],t[3][2],t[3][3]),s=this.vox2mm([0,0,0],n),r=this.vox2mm([1,0,0],n);jt(r,r,s);const c=this.vox2mm([0,1,0],n);jt(c,c,s);const l=this.vox2mm([0,0,1],n);jt(l,l,s),this.hdr.pixDims[1]=wn(r),this.hdr.pixDims[2]=wn(c),this.hdr.pixDims[3]=wn(l)}readECAT(t){this.hdr=new ut;const n=this.hdr;n.dims=[3,1,1,1,0,0,0,0],n.pixDims=[1,1,1,1,1,0,0,0];const s=new DataView(t),r=s.getInt32(0,!1),c=s.getInt16(50,!1);if(r!==1296127058||c<1||c>14)throw new Error("Not a valid ECAT file");let l=512,d=0;const h=[];let u=new Float32Array;for(;;){const m=s.getInt32(l,!1),g=s.getInt32(l+12,!1);if(m+g!==31)break;let A=l+20,v=0,y=0;for(;v<31&&(y=s.getInt32(A,!1),A+=16,y!==0);){v++;let w=y*512;const b=w-512,C=s.getUint16(b,!1);n.dims[1]=s.getUint16(b+4,!1),n.dims[2]=s.getUint16(b+6,!1),n.dims[3]=s.getUint16(b+8,!1);const S=s.getFloat32(b+26,!1);n.pixDims[1]=s.getFloat32(b+34,!1)*10,n.pixDims[2]=s.getFloat32(b+38,!1)*10,n.pixDims[3]=s.getFloat32(b+42,!1)*10,n.pixDims[4]=s.getUint32(b+46,!1)/1e3,h.push(n.pixDims[4]);const E=n.dims[1]*n.dims[2]*n.dims[3],M=new Float32Array(E);if(C===1)for(let U=0;U1){n.dims[0]=4;let m=!1;for(let g=0;gM===l[N]))throw new Error("Not a valid NPY file: Magic number mismatch");const d=r.getUint16(8,!0),h=new TextDecoder("utf-8").decode(t.slice(10,10+d)),u=h.match(/'shape': \((.*?)\)/);if(!u)throw new Error("Invalid NPY header: Shape not found");const m=u[1].split(",").map(M=>M.trim()).filter(M=>M!=="").map(Number),g=h.match(/'descr': '([^']+)'/);if(!g)throw new Error("Invalid NPY header: Data type not found");const A=g[1],v=m.reduce((M,N)=>M*N,1),y=10+d,w=t.slice(y,y+v*n(A)),b=m.length>0?m[m.length-1]:1,C=m.length>1?m[m.length-2]:1,S=m.length>2?m[m.length-3]:1;this.hdr=new ut;const E=this.hdr;return E.dims=[3,b,C,S,0,0,0,0],E.pixDims=[1,1,1,1,1,0,0,0],E.affine=[[E.pixDims[1],0,0,-(E.dims[1]-2)*.5*E.pixDims[1]],[0,-E.pixDims[2],0,(E.dims[2]-2)*.5*E.pixDims[2]],[0,0,-E.pixDims[3],(E.dims[3]-2)*.5*E.pixDims[3]],[0,0,0,1]],E.numBitsPerVoxel=n(A)*8,E.datatypeCode=s(A),w}async readNPZ(t){const n=new Q2(t);for(let s=0;s{const r=new Blob([t]),c=URL.createObjectURL(r),l=new Image;l.crossOrigin="Anonymous",l.src=c,l.onload=()=>{URL.revokeObjectURL(c);const d=document.createElement("canvas");d.width=l.width,d.height=l.height;const h=d.getContext("2d");if(!h){s(new Error("Failed to get 2D context"));return}h.drawImage(l,0,0),n(h.getImageData(0,0,l.width,l.height))},l.onerror=d=>{URL.revokeObjectURL(c),s(d)}})}async readBMP(t){const n=await this.imageDataFromArrayBuffer(t),{width:s,height:r,data:c}=n;this.hdr=new ut;const l=this.hdr;l.dims=[3,s,r,1,0,0,0,0],l.pixDims=[1,1,1,1,1,0,0,0],l.affine=[[l.pixDims[1],0,0,-(l.dims[1]-2)*.5*l.pixDims[1]],[0,-l.pixDims[2],0,(l.dims[2]-2)*.5*l.pixDims[2]],[0,0,-l.pixDims[3],(l.dims[3]-2)*.5*l.pixDims[3]],[0,0,0,1]],l.numBitsPerVoxel=8,l.datatypeCode=2304;let d=!0;for(let h=0;h=4){let l=8+c;const d=s.getUint32(l+88,!0);if(l=l+92,d>0){const h=t.byteLength;for(let u=0;u1&&(n.dims[0]=4),n.pixDims[1]=s.voxel_size[0],n.pixDims[2]=s.voxel_size[1],n.pixDims[3]=s.voxel_size[2],n.sform_code=1;const l=(n.dims[1]-1)*.5*n.pixDims[1],d=(n.dims[2]-1)*.5*n.pixDims[2],h=(n.dims[3]-1)*.5*n.pixDims[3];n.affine=[[n.pixDims[1],0,0,-l],[0,-n.pixDims[2],0,d],[0,0,n.pixDims[2],-h],[0,0,0,1]],n.littleEndian=!0;const u=n.dims[1]*n.dims[2]*n.dims[3]*(n.numBitsPerVoxel/8),m=u*n.dims[4],g=new Uint8Array(new ArrayBuffer(m));let A=0;for(let v=0;v2&&(w=w.slice(2)),h.startsWith("BinaryDataByteOrderMSB")&&w[0].includes("False")&&(u.littleEndian=!0),h.startsWith("BinaryDataByteOrderMSB")&&w[0].includes("True")&&(u.littleEndian=!1),h.startsWith("CompressedData")&&w[0].includes("True")&&(m=!0),h.startsWith("TransformMatrix"))for(let b=0;b<9;b++)A[b]=parseFloat(w[b]);if(h.startsWith("Offset"))for(let b=0;b2||R.length!==4)break;s.affine[g][0]=parseFloat(R[0]),s.affine[g][1]=parseFloat(R[1]),s.affine[g][2]=parseFloat(R[2]),s.affine[g][3]=parseFloat(R[3]),g++;break;case"comments":s.description=R[0].substring(0,Math.min(79,R[0].length));break;case"RepetitionTime":A=parseFloat(R[0]);break;case"file":v=!R[0].startsWith(". "),v||(R=R[0].split(" "),s.vox_offset=parseInt(R[1]));break}}const y=s.dims[0];y>5&&k.warn("reader only designed for a maximum of 5 dimensions (XYZTD)");let w=1;for(let R=0;R0&&(s.pixDims[4]=A),v&&!n&&k.warn("MIH header provided without paired image data");let b;if(n&&v)b=n.slice(0);else if(m){s.numBitsPerVoxel=8;const R=new Uint8Array(w),Y=t.slice(s.vox_offset,s.vox_offset+Math.ceil(w/8)),P=new Uint8Array(Y);let X=0;for(let L=0;L>7-H&1,H===7&&X++}b=R.buffer}else b=t.slice(s.vox_offset,s.vox_offset+w*(s.numBitsPerVoxel/8));u.length!==s.dims[0]&&k.warn("dims does not match layout");let C=1;const S=[1,1,1,1,1],E=[!1,!1,!1,!1,!1];for(let R=0;Rs[0]&&(r[0]=2),s[6]>s[0]&&s[6]>s[3]&&(r[0]=3),r[1]=1,r[0]===1?s[4]>s[7]?r[1]=2:r[1]=3:r[0]===2?s[1]>s[7]?r[1]=1:r[1]=3:s[1]>s[4]?r[1]=1:r[1]=2,r[2]=6-r[1]-r[0];let c=[1,2,3];c[r[0]-1]=1,c[r[1]-1]=2,c[r[2]-1]=3;let l=oi(t[0][0],t[0][1],t[0][2],t[0][3],t[1][0],t[1][1],t[1][2],t[1][3],t[2][0],t[2][1],t[2][2],t[2][3],0,0,0,1);this.mm000=this.vox2mm([-.5,-.5,-.5],l),this.mm100=this.vox2mm([n.dims[1]-.5,-.5,-.5],l),this.mm010=this.vox2mm([-.5,n.dims[2]-.5,-.5],l),this.mm001=this.vox2mm([-.5,-.5,n.dims[3]-.5],l);const d=Ut();ep(d,l);for(let b=0;b<3;b++)for(let C=0;C<3;C++)d[b*4+C]=l[b*4+c[C]-1];const h=[0,0,0];d[0]<0&&(h[0]=1),d[5]<0&&(h[1]=1),d[10]<0&&(h[2]=1),this.dimsRAS=[n.dims[0],n.dims[c[0]],n.dims[c[1]],n.dims[c[2]]],this.pixDimsRAS=[n.pixDims[0],n.pixDims[c[0]],n.pixDims[c[1]],n.pixDims[c[2]]],this.permRAS=c.slice();for(let b=0;b<3;b++)h[b]===1&&(this.permRAS[b]=-this.permRAS[b]);if(this.arrayEquals(c,[1,2,3])&&this.arrayEquals(h,[0,0,0])){this.toRAS=Ut(),this.matRAS=re(l),this.calculateOblique(),this.img2RASstep=[1,this.dimsRAS[1],this.dimsRAS[1]*this.dimsRAS[2]],this.img2RASstart=[0,0,0];return}C2(l),l[0]=1-h[0]*2,l[5]=1-h[1]*2,l[10]=1-h[2]*2,l[3]=(n.dims[c[0]]-1)*h[0],l[7]=(n.dims[c[1]]-1)*h[1],l[11]=(n.dims[c[2]]-1)*h[2];const u=Ut();Pe(u,l),qn(u,u,d),this.matRAS=re(u),l=oi(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),l[c[0]-1+0]=-h[0]*2+1,l[c[1]-1+4]=-h[1]*2+1,l[c[2]-1+8]=-h[2]*2+1,l[3]=h[0],l[7]=h[1],l[11]=h[2],this.toRAS=re(l),l[3]=0,l[7]=0,l[11]=0,l[12]=0,(this.permRAS[0]===-1||this.permRAS[1]===-1||this.permRAS[2]===-1)&&(l[12]=n.dims[1]-1),l[13]=0,(this.permRAS[0]===-2||this.permRAS[1]===-2||this.permRAS[2]===-2)&&(l[13]=n.dims[2]-1),l[14]=0,(this.permRAS[0]===-3||this.permRAS[1]===-3||this.permRAS[2]===-3)&&(l[14]=n.dims[3]-1),this.toRASvox=re(l),k.debug(this.hdr.dims),k.debug(this.dimsRAS);const m=this.hdr;c=this.permRAS;const g=[Math.abs(c[0]),Math.abs(c[1]),Math.abs(c[2])],A=[m.dims[g[0]],m.dims[g[1]],m.dims[g[2]]],v=[1,m.dims[1],m.dims[1]*m.dims[2]],y=[v[g[0]-1],v[g[1]-1],v[g[2]-1]],w=[0,0,0];for(let b=0;b<3;b++)c[b]<0&&(w[b]=y[b]*(A[b]-1),y[b]=-y[b]);this.img2RASstep=y,this.img2RASstart=w,this.calculateOblique()}async hdr2RAS(t=1){if(!this.permRAS)throw new Error("permRAS undefined");if(!this.hdr)throw new Error("hdr undefined");const n=Kl({...this.hdr,vox_offset:352},!1),s=await Ka(n.buffer,!0);t===1?(s.dims[0]=3,s.dims[4]=1):t>1&&(s.dims[0]=4,s.dims[4]=t);const r=this.permRAS.slice();if(r[0]===1&&r[1]===2&&r[2]===3)return s;s.qform_code=0;for(let l=1;l<4;l++)s.dims[l]=this.dimsRAS[l];for(let l=0;lthis.img.length||c<0)&&(c=0,k.warn(`img2RAS nVolume (${t}) out of bounds (${t}+1)×${r} > ${this.img.length}`));const l=this.img.slice(0,r),d=[Math.abs(n[0]),Math.abs(n[1]),Math.abs(n[2])],h=[s.dims[d[0]],s.dims[d[1]],s.dims[d[2]]],u=[1,s.dims[1],s.dims[1]*s.dims[2]],m=[u[d[0]-1],u[d[1]-1],u[d[2]-1]],g=[0,0,0];for(let v=0;v<3;v++)n[v]<0&&(g[v]=m[v]*(h[v]-1),m[v]=-m[v]);let A=0;for(let v=0;vs===n[r])}setColormap(t){this._colormap=t,this.calMinMax(),this.onColormapChange&&this.onColormapChange(this)}setColormapLabel(t){this.colormapLabel=Pt.makeLabelLut(t)}async setColormapLabelFromUrl(t){this.colormapLabel=await Pt.makeLabelLutFromUrl(t)}get colormap(){return this._colormap}get colorMap(){return this._colormap}set colormap(t){this.setColormap(t)}set colorMap(t){this.setColormap(t)}get opacity(){return this._opacity}set opacity(t){this._opacity=t,this.onOpacityChange&&this.onOpacityChange(this)}calMinMax(t=Number.POSITIVE_INFINITY,n=!0){if(!this.hdr)throw new Error("hdr undefined");if(!this.img)throw new Error("img undefined");let s=Number.POSITIVE_INFINITY,r=Number.NEGATIVE_INFINITY,c=0,l=0,d=this.hdr.dims[1]*this.hdr.dims[2]*this.hdr.dims[3];const h=Math.floor(this.img.length/d);t>=h&&(t=this.frame4D),t=Math.min(t,h-1);const u=t*d;let m=[];if(n){const Y=[Math.floor(.25*this.hdr.dims[1]),Math.floor(.25*this.hdr.dims[2]),Math.floor(.25*this.hdr.dims[3])],P=[this.hdr.dims[1]-2*Y[0],this.hdr.dims[2]-2*Y[1],this.hdr.dims[3]-2*Y[2]],X=[P[0]+Y[0],P[1]+Y[1],P[2]+Y[2]];d=P[0]*P[1]*P[2],m=new this.img.constructor(d);let L=-1,H=0;for(let W=0;W=X[0]||at>=X[1]||W>=X[2]||(m[H]=this.img[L+u],H++))}else{m=new this.img.constructor(d);for(let R=0;R0&&(s=0);const A=this.intensityRaw2Scaled(s),v=this.intensityRaw2Scaled(r),y=Pt.colormapFromKey(this._colormap);let w=0,b=0;if(y.min!==void 0&&(w=y.min),y.max!==void 0&&(b=y.max),w===b&&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=A,this.global_max=v,[this.hdr.cal_min,this.hdr.cal_max,this.hdr.cal_min,this.hdr.cal_max];if(w!==b)return this.cal_min=w,this.cal_max=b,this.robust_min=this.cal_min,this.robust_max=this.cal_max,[w,b,w,b];const C=100*c/(d-0);let S=!1;C>60&&!this.ignoreZeroVoxels&&(k.warn(`${Math.round(C)}% of voxels are zero: ignoring zeros for cal_max`),S=!0,this.ignoreZeroVoxels=!0),this.ignoreZeroVoxels||(c=0),c+=l;const E=Math.round((d-0-c)*this.percentileFrac);if(E<1||s===r)return n?this.calMinMax(t,!1):(k.debug("no variability in image intensity?"),this.cal_min=A,this.cal_max=v,this.robust_min=this.cal_min,this.robust_max=this.cal_max,this.global_min=A,this.global_max=v,[A,v,A,v]);const M=1001,N=(M-1)/(r-s),U=new Array(M);for(let R=0;R0&&(F--,U[F]>0&&(R=0)),R!==0&&I0&&(R=0)),F===0&&I===M-1&&(R=0)}let B=this.intensityRaw2Scaled(F/N+s),V=this.intensityRaw2Scaled(I/N+s);return this.hdr.cal_min=A&&this.hdr.cal_max<=v&&(B=this.hdr.cal_min,V=this.hdr.cal_max),S&&(B=Math.min(B,0)),this.cal_min=B,this.cal_max=V,this.hdr.intent_code===1002&&(this.cal_min=A,this.cal_max=v),this.robust_min=this.cal_min,this.robust_max=this.cal_max,this.global_min=A,this.global_max=v,[B,V,A,v]}intensityRaw2Scaled(t){if(!this.hdr)throw new Error("hdr undefined");return this.hdr.scl_slope===0&&(this.hdr.scl_slope=1),t*this.hdr.scl_slope+this.hdr.scl_inter}intensityScaled2Raw(t){if(!this.hdr)throw new Error("hdr undefined");return this.hdr.scl_slope===0&&(this.hdr.scl_slope=1),(t-this.hdr.scl_inter)/this.hdr.scl_slope}async saveToUint8Array(t,n=null){return J2(this,t,n)}async saveToDisk(t="",n=null){return d4(this,t,n)}static async fetchDicomData(t,n={}){if(t==="")throw Error("url must not be empty");let r=/^(?:[a-z+]+:)?\/\//i.test(t)?t:new URL(t,window.location.href);/(?:.([^.]+))?$/.exec(r.pathname)||(r=new URL("niivue-manifest.txt",t));let d=await fetch(r,{headers:n});if(!d.ok)throw Error(d.statusText);const u=(await d.text()).split(` +`),g=/(.*\/).*/.exec(r)[0],A=[];for(const v of u){const y=new URL(v,g);if(d=await fetch(y,{headers:n}),!d.ok)throw Error(d.statusText);const w=await d.arrayBuffer();A.push({name:v,data:w})}return A}static async readFirstDecompressedBytes(t,n){const s=t.getReader(),r=new Op,c=[];let l=0,d=!1,h,u;const m=new Promise((A,v)=>{h=A,u=v});function g(){const A=new Uint8Array(l);let v=0;for(const y of c)A.set(y,v),v+=y.length;h(A)}return r.ondata=A=>{c.push(A),l+=A.length,l>=n&&(d=!0,s.cancel().catch(()=>{}),g())},(async()=>{try{for(;!d;){const{done:A,value:v}=await s.read();if(A){d=!0,r.push(new Uint8Array,!0);return}r.push(v,!1)}}catch(A){u(A)}})().catch(()=>{}),m}static extractFilenameFromUrl(t){const s=new URL(t).searchParams.get("response-content-disposition");if(s){const r=s.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/);if(r)return decodeURIComponent(r[1])}return t.split("/").pop().split("?")[0]}static async loadInitialVolumesGz(t="",n={},s=NaN){if(isNaN(s))return null;const r=await fetch(t,{headers:n,cache:"force-cache"});let c=352,l=await this.readFirstDecompressedBytes(r.body,c);const d=new DataView(l.buffer,l.byteOffset,l.byteLength),h=d.getUint16(0,!0),u=h===348;if(!u&&!(h===23553)||(l.length>111&&(c=d.getFloat32(108,u)),c>l.length&&(l=await this.readFirstDecompressedBytes(r.body,c)),!(l[0]===92&&l[1]===1||l[1]===92&&l[0]===1)))return null;const A=await Ka(l.buffer);if(!A)throw new Error("Could not read NIfTI header");const v=A.numBitsPerVoxel/8,y=[1,2,3].reduce((M,N)=>M*(A.dims[N]>1?A.dims[N]:1),1),w=[4,5,6].reduce((M,N)=>M*(A.dims[N]>1?A.dims[N]:1),1),b=Math.max(Math.min(s,w),1),C=A.vox_offset+b*y*v;if(b===w)return null;const S=await fetch(t,{headers:n,cache:"force-cache"});return(await this.readFirstDecompressedBytes(S.body,C)).buffer.slice(0,C)}static async loadInitialVolumes(t="",n={},s=NaN){if(isNaN(s))return null;const c=(await fetch(t,{headers:n,cache:"force-cache"})).body.getReader(),{value:l,done:d}=await c.read();let h=l;if(d||!h||h.length<2)throw new Error("Not enough data to determine compression");const u=new DataView(h.buffer,h.byteOffset,h.byteLength),m=u.getUint16(0,!0);if(m===35615)return await c.cancel(),this.loadInitialVolumesGz(t,n,s);const A=m===348;if(!A&&!(m===23553))return await c.cancel(),null;let y=352;for(h.length>111&&(y=u.getFloat32(108,A));h.lengthF*(w.dims[I]>1?w.dims[I]:1),1),S=[4,5,6].reduce((F,I)=>F*(w.dims[I]>1?w.dims[I]:1),1),E=Math.max(Math.min(s,S),1),M=w.vox_offset+E*C*b,N=new Uint8Array(M),U=Math.min(h.length,M);N.set(h.subarray(0,U),0);let T=U;for(;T0&&(t=E),t instanceof ArrayBuffer)if(N=t,r!=="")t=r;else{const V=new Uint8Array(N);t=V[0]===31&&V[1]===139?"array.nii.gz":"array.nii"}function T(V){const R=V.match(/\.([^.]+)(?:\.gz|\.bz2|\.xz)?$/);return R?R[1]:""}let F="";if(r===""?F=T(t):F=T(r),C===bt.UNKNOWN&&(C=bt.parse(F)),C===bt.UNKNOWN&&typeof t=="string"){const V=await fetch(t,{});if(V.redirected){const R=this.extractFilenameFromUrl(V.url);R&&R.length>0&&r===""&&(r=R,F=T(r),C=bt.parse(F))}}if(C===bt.ZARR){const V=new URL(t).searchParams,R=V.get("z"),Y=V.get("y"),P=V.get("x"),X=R?Ja(parseInt(R),parseInt(R)+1):null,L=Y?Ja(parseInt(Y),parseInt(Y)+1):null,H=P?Ja(parseInt(P),parseInt(P)+1):null,W=t.split("?")[0],at=new _p(W),ct=p5(at);let G;try{G=await yn(ct.resolve(t),{kind:"array"})}catch{G=await yn(ct,{kind:"array"})}let j;if(G.shape.length===4){const Rt=G.shape[2],Mt=G.shape[1],_t=G.shape[0];X&&X[0]>=Rt&&(X[0]=Rt-1),L&&L[0]>=Mt&&(L[0]=Mt-1),H&&H[0]>=_t&&(H[0]=_t-1),j=await $d(G,[H,L,X,null])}else j=await $d(G,[H,L,X]);N=j.data;const[$,et,ot,mt]=j.shape;U={data:N,width:et,height:$,depth:ot,channels:mt}}const I=C===bt.DCM||bt.NII;if(!N&&I&&(N=await this.loadInitialVolumes(t,s,b)),!N)if(w)N=await Hl.fetchDicomData(t,s),C=bt.DCM_MANIFEST;else{const V=await fetch(t,{headers:s});if(!V.ok)throw Error(V.statusText);if(!V.body)throw new Error("No readable stream available");const R=await Fh(V.body),Y=[],P=R.getReader();for(;;){const{done:W,value:at}=await P.read();if(W)break;Y.push(at)}const X=Y.reduce((W,at)=>W+at.length,0);N=new ArrayBuffer(X);const L=new Uint8Array(N);let H=0;for(const W of Y)L.set(W,H),H+=W.length}F.toUpperCase()==="HEAD"&&n===""&&(n=t.substring(0,t.lastIndexOf("HEAD"))+"BRIK"),F.toUpperCase()==="HDR"&&n===""&&(n=t.substring(0,t.lastIndexOf("HDR"))+"IMG");let B=null;if(n)try{let V=await fetch(n,{headers:s});if(V.status===404&&(n.includes("BRIK")||n.includes("IMG"))&&(V=await fetch(`${n}.gz`,{headers:s})),V.ok&&V.body){const R=await Fh(V.body),Y=[],P=R.getReader();for(;;){const{done:W,value:at}=await P.read();if(W)break;Y.push(at)}const X=Y.reduce((W,at)=>W+at.length,0);B=new ArrayBuffer(X);const L=new Uint8Array(B);let H=0;for(const W of Y)L.set(W,H),H+=W.length}}catch(V){console.error("Error loading paired image data:",V)}if(!N)throw new Error("Unable to load buffer properly from volume");if(!r){let V;try{V=new URL(t).pathname.split("/")}catch{V=t.split("/")}r=V.slice(-1)[0],r.indexOf("?")>-1&&(r=r.slice(0,r.indexOf("?")))}return M=await this.new(N,r,c,l,B,d,h,u,m,g,A,v,y,C,NaN,NaN,!0,null,0,U),M.url=t,M.colorbarVisible=S,M}static async readFileAsync(t,n=NaN){let s=t.stream();if(!isNaN(n)){let g=0;const A=new TransformStream({transform(v,y){if(g>=n){y.terminate();return}const w=n-g;v.length>w?(y.enqueue(v.slice(0,w)),y.terminate()):y.enqueue(v),g+=v.length}});s=s.pipeThrough(A)}const r=await Fh(s),c=[],l=r.getReader();for(;;){const{done:g,value:A}=await l.read();if(g)break;c.push(A)}const d=c.reduce((g,A)=>g+A.length,0),h=new ArrayBuffer(d),u=new Uint8Array(h);let m=0;for(const g of c)u.set(g,m),m+=g.length;return h}static async loadFromFile({file:t,name:n="",colormap:s="",opacity:r=1,urlImgData:c=null,cal_min:l=NaN,cal_max:d=NaN,trustCalMinMax:h=!0,percentileFrac:u=.02,ignoreZeroVoxels:m=!1,useQFormNotSForm:g=!1,colormapNegative:A="",frame4D:v=0,limitFrames4D:y=NaN,imageType:w=bt.UNKNOWN}){let b=null,C=[];try{if(Array.isArray(t))C=await Promise.all(t.map(E=>this.readFileAsync(E)));else{if(isNaN(y))C=await this.readFileAsync(t);else{const E=await this.readFileAsync(t,512),M=new Uint8Array(E);if(!(M[0]===92&&M[1]===1||M[1]===92&&M[0]===1))C=await this.readFileAsync(t);else{const U=await Ka(E);if(!U)throw new Error("could not read nifti header");const T=U.numBitsPerVoxel/8,F=[1,2,3].reduce((R,Y)=>R*(U.dims[Y]>1?U.dims[Y]:1),1),I=[4,5,6].reduce((R,Y)=>R*(U.dims[Y]>1?U.dims[Y]:1),1),B=Math.max(Math.min(y,I),1),V=U.vox_offset+B*F*T;C=await this.readFileAsync(t,V)}}n=t.name}let S=null;c&&(S=await this.readFileAsync(c)),b=await this.new(C,n,s,r,S,l,d,h,u,m,g,A,v,w,NaN,NaN,!0,null,0,null),b.fileObject=t}catch(S){throw k.error(S),new Error("could not build NVImage")}if(b===null)throw new Error("could not build NVImage");return b}static createNiftiArray(t=[256,256,256],n=[1,1,1],s=[1,0,0,-128,0,1,0,-128,0,0,1,-128,0,0,0,1],r=2,c=new Uint8Array){return f4(t,n,s,r,c)}static createNiftiHeader(t=[256,256,256],n=[1,1,1],s=[1,0,0,-128,0,1,0,-128,0,0,1,-128,0,0,0,1],r=2){return W2(t,n,s,r)}getVolumeData(t=[-1,0,0],n=[0,0,0],s="same"){return g4(this,t,n,s)}setVolumeData(t=[-1,0,0],n=[0,0,0],s=new Uint8Array){A4(this,t,n,s)}static async loadFromBase64({base64:t,name:n="",colormap:s="",opacity:r=1,cal_min:c=NaN,cal_max:l=NaN,trustCalMinMax:d=!0,percentileFrac:h=.02,ignoreZeroVoxels:u=!1,useQFormNotSForm:m=!1,colormapNegative:g="",frame4D:A=0,imageType:v=bt.UNKNOWN,cal_minNeg:y=NaN,cal_maxNeg:w=NaN,colorbarVisible:b=!0,colormapLabel:C=null}){function S(M){const N=window.atob(M),U=N.length,T=new Uint8Array(U);for(let F=0;F"u")return c;if(!n){const d=re(this.frac2mmOrtho);return Pe(d,d),De(s,s,d),c[0]=s[0],c[1]=s[1],c[2]=s[2],c}if(r[1]<1||r[2]<1||r[3]<1)return c;const l=re(this.matRAS);return Pe(l,l),We(l,l),De(s,s,l),c[0]=(s[0]+.5)/r[1],c[1]=(s[1]+.5)/r[2],c[2]=(s[2]+.5)/r[3],c}},am=(i=>(i[i.none=0]="none",i[i.contrast=1]="contrast",i[i.measurement=2]="measurement",i[i.pan=3]="pan",i[i.slicer3D=4]="slicer3D",i[i.callbackOnly=5]="callbackOnly",i[i.roiSelection=6]="roiSelection",i[i.angle=7]="angle",i[i.crosshair=8]="crosshair",i[i.windowing=9]="windowing",i))(am||{}),mi={textHeight:-1,fontSizeScaling:.4,fontMinPx:13,colorbarHeight:.05,colorbarWidth:-1,showColorbarBorder:!0,crosshairWidth:1,crosshairWidthUnit:"voxels",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],isClipPlanesCutaway:!1,paqdUniforms:[.3,.5,.5,1],rulerColor:[1,0,0,.8],colorbarMargin:.05,trustCalMinMax:!0,clipPlaneHotKey:"KeyC",cycleClipPlaneHotKey:"KeyP",viewModeHotKey:"KeyV",doubleTouchTimeout:500,longTouchTimeout:1e3,keyDebounceTime:50,isNearestInterpolation:!1,isResizeCanvas:!0,atlasOutline:0,atlasActiveIndex:0,isRuler:!1,isColorbar:!1,isOrientCube:!1,tileMargin:0,multiplanarPadPixels:0,multiplanarForceRender:!1,multiplanarEqualSize:!1,multiplanarShowRender:2,isRadiologicalConvention:!1,meshThicknessOn2D:1/0,dragMode:1,dragModePrimary:8,mouseEventConfig:void 0,touchEventConfig:void 0,yoke3Dto2DZoom:!1,isDepthPickMesh:!1,isCornerOrientationText:!1,isOrientationTextVisible:!0,showAllOrientationMarkers:!1,heroImageFraction:0,heroSliceType:4,sagittalNoseLeft:!1,isSliceMM:!1,isV1SliceShader:!1,forceDevicePixelRatio:0,logLevel:"info",loadingText:"loading ...",isForceMouseClickToVoxelCenters:!1,dragAndDropEnabled:!0,drawingEnabled:!1,penValue:1,penType:0,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:"",centerMosaic:!1,penSize:1,interactive:!0,clickToSegment:!1,clickToSegmentRadius:3,clickToSegmentBright:!0,clickToSegmentAutoIntensity:!1,clickToSegmentIntensityMax:NaN,clickToSegmentIntensityMin:NaN,clickToSegmentPercent:0,clickToSegmentMaxDistanceMM:Number.POSITIVE_INFINITY,clickToSegmentIs2D:!1,selectionBoxLineThickness:4,selectionBoxIsOutline:!1,scrollRequiresFocus:!1,showMeasureUnits:!0,measureTextJustify:"center",measureTextColor:[1,0,0,1],measureLineColor:[1,0,0,1],measureTextHeight:.06,isAlphaClipDark:!1,gradientOrder:1,gradientOpacity:0,renderSilhouette:0,gradientAmount:0,invertScrollDirection:!1,is2DSliceShader:!1,bounds:null,showBoundsBorder:!1,boundsBorderColor:[1,1,1,1]},Za={gamma:1,azimuth:110,elevation:10,crosshairPos:lt(.5,.5,.5),clipPlanes:[[0,0,0,0]],clipPlaneDepthAziElevs:[[2,0,0]],volScaleMultiplier:1,pan2Dxyzmm:te(0,0,0,1)};function y4(i,t){const n={};for(const s in i){const r=i[s],c=t[s],l=Array.isArray(r)&&Array.isArray(c);(l&&r.some((d,h)=>d!==c[h])||!l&&r!==c)&&(n[s]=r)}return n}var Bh=class An{constructor(){z(this,"data",{title:"Untitled document",imageOptionsArray:[],meshOptionsArray:[],opts:{...mi},previewImageDataURL:"",labels:[],encodedImageBlobs:[],encodedDrawingBlob:""}),z(this,"scene"),z(this,"volumes",[]),z(this,"meshDataObjects"),z(this,"meshes",[]),z(this,"drawBitmap",null),z(this,"imageOptionsMap",new Map),z(this,"meshOptionsMap",new Map),z(this,"completedMeasurements",[]),z(this,"completedAngles",[]),z(this,"_optsProxy",null),z(this,"_optsChangeCallback",null),this.scene={onAzimuthElevationChange:()=>{},onZoom3DChange:()=>{},sceneData:{...Za,pan2Dxyzmm:te(0,0,0,1),crosshairPos:lt(.5,.5,.5)},get renderAzimuth(){return this.sceneData.azimuth},set renderAzimuth(t){this.sceneData.azimuth=t,this.onAzimuthElevationChange&&this.onAzimuthElevationChange(this.sceneData.azimuth,this.sceneData.elevation)},get renderElevation(){return this.sceneData.elevation},set renderElevation(t){this.sceneData.elevation=t,this.onAzimuthElevationChange&&this.onAzimuthElevationChange(this.sceneData.azimuth,this.sceneData.elevation)},get volScaleMultiplier(){return this.sceneData.volScaleMultiplier},set volScaleMultiplier(t){this.sceneData.volScaleMultiplier=t,this.onZoom3DChange(t)},get crosshairPos(){return this.sceneData.crosshairPos},set crosshairPos(t){this.sceneData.crosshairPos=t},get clipPlane(){return this.sceneData.clipPlanes[0]??[]},set clipPlane(t){this.sceneData.clipPlanes[0]=t},get clipPlanes(){return this.sceneData.clipPlanes},set clipPlanes(t){this.sceneData.clipPlanes=t},get clipPlaneDepthAziElevs(){return this.sceneData.clipPlaneDepthAziElevs},set clipPlaneDepthAziElevs(t){this.sceneData.clipPlaneDepthAziElevs=t},get pan2Dxyzmm(){return this.sceneData.pan2Dxyzmm},set pan2Dxyzmm(t){this.sceneData.pan2Dxyzmm=t},get gamma(){return this.sceneData.gamma},set gamma(t){this.sceneData.gamma=t}}}get title(){return this.data.title}get previewImageDataURL(){return this.data.previewImageDataURL}set previewImageDataURL(t){this.data.previewImageDataURL=t}set title(t){this.data.title=t}get imageOptionsArray(){return this.data.imageOptionsArray}get encodedImageBlobs(){return this.data.encodedImageBlobs}get encodedDrawingBlob(){return this.data.encodedDrawingBlob}get opts(){return this._optsProxy||this._createOptsProxy(),this._optsProxy}set opts(t){this.data.opts={...t},this._optsProxy=null}get labels(){return this.data.labels}set labels(t){this.data.labels=t}get customData(){return this.data.customData}set customData(t){this.data.customData=t}hasImage(t){return this.volumes.find(n=>n.id===t.id)!==void 0}hasImageFromUrl(t){return this.data.imageOptionsArray.find(n=>n.url===t)!==void 0}addImageOptions(t,n){if(!this.hasImage(t)&&!n.name)if(n.url){const r=/^(?:[a-z+]+:)?\/\//i.test(n.url)?new URL(n.url):new URL(n.url,window.location.href);n.name=r.pathname.split("/").pop(),n.name.toLowerCase().endsWith(".gz")&&(n.name=n.name.slice(0,-3)),n.name.toLowerCase().endsWith(".nii")||(n.name+=".nii")}else n.name="untitled.nii";n.imageType=bt.NII,this.data.imageOptionsArray.push(n),this.imageOptionsMap.set(t.id,this.data.imageOptionsArray.length-1)}removeImage(t){if(this.imageOptionsMap.has(t.id)){const n=this.imageOptionsMap.get(t.id);this.data.imageOptionsArray.length>n&&this.data.imageOptionsArray.splice(n,1),this.imageOptionsMap.delete(t.id)}this.volumes=this.volumes.filter(n=>n.id!==t.id)}async fetchLinkedData(){if(this.data.encodedImageBlobs=[],!!this.imageOptionsArray?.length){for(const t of this.imageOptionsArray)if(t.url)try{const n=await fetch(t.url);if(!n.ok){console.warn("Failed to fetch image:",t.url);continue}const s=await n.arrayBuffer(),r=new Uint8Array(s),c=At.uint8tob64(r);this.data.encodedImageBlobs.push(c),console.info("fetch linked data fetched from ",t.url)}catch(n){console.warn(`Failed to fetch/encode image from ${t.url}:`,n)}}}getImageOptions(t){return this.imageOptionsMap.has(t.id)?this.data.imageOptionsArray[this.imageOptionsMap.get(t.id)]:null}json(t=!0,n=!0){const s={encodedImageBlobs:[],previewImageDataURL:this.data.previewImageDataURL,imageOptionsMap:new Map},r=[];s.sceneData={...this.scene.sceneData},delete s.sceneData.clipPlane,delete s.sceneData.clipPlaneDepthAziElev,delete s.sceneData.clipThick,delete s.sceneData.clipVolumeLow,delete s.sceneData.clipVolumeHigh,s.opts=y4(this.opts,mi),this.opts.meshThicknessOn2D===1/0&&(s.opts.meshThicknessOn2D="infinity"),this.opts.meshThicknessOn2D===1/0&&(s.opts.meshThicknessOn2D="infinity"),s.labels=[...this.data.labels];for(const l of s.labels)delete l.onClick;if(s.customData=this.customData,s.completedMeasurements=[...this.completedMeasurements],s.completedAngles=[...this.completedAngles],this.volumes.length)for(let l=0;l({values:h.values,nFrame4D:h.nFrame4D,frame4D:0,outlineBorder:h.outlineBorder,global_min:h.global_min,global_max:h.global_max,cal_min:h.cal_min,cal_max:h.cal_max,opacity:h.opacity,colormap:h.colormap,colormapNegative:h.colormapNegative,colormapLabel:h.colormapLabel,useNegativeCmap:h.useNegativeCmap})),hasConnectome:l.hasConnectome,edgeColormap:l.edgeColormap,edgeColormapNegative:l.edgeColormapNegative,edgeMax:l.edgeMax,edgeMin:l.edgeMin,edges:l.edges&&Array.isArray(l.edges)?[...l.edges]:[],extentsMax:l.extentsMax,extentsMin:l.extentsMin,furthestVertexFromOrigin:l.furthestVertexFromOrigin,nodeColormap:l.nodeColormap,nodeColormapNegative:l.nodeColormapNegative,nodeMaxColor:l.nodeMaxColor,nodeMinColor:l.nodeMinColor,nodeScale:l.nodeScale,legendLineThickness:l.legendLineThickness,offsetPt0:l.offsetPt0,nodes:l.nodes};l.offsetPt0&&l.offsetPt0.length>0&&(d.offsetPt0=l.offsetPt0,d.fiberGroupColormap=l.fiberGroupColormap,d.fiberColor=l.fiberColor,d.fiberDither=l.fiberDither,d.fiberRadius=l.fiberRadius,d.colormap=l.colormap),c.push(d)}return s.meshesString=JSON.stringify(Sp(c)),n&&this.drawBitmap&&(s.encodedDrawingBlob=At.uint8tob64(this.drawBitmap)),s}async download(t,n,s={embedImages:!0}){const r=this.json(s.embedImages),c=JSON.stringify(r),l=n?"application/gzip":"application/json",d=n?await At.compressStringToArrayBuffer(c):c;At.download(d,t,l)}static deserializeMeshDataObjects(t){if(!t.data.meshesString||t.data.meshesString==="[]"){t.meshDataObjects=[];return}if(t.data.meshesString){t.meshDataObjects=yp(JSON.parse(t.data.meshesString));for(const n of t.meshDataObjects)for(const s of n.layers)"colorMap"in s&&(s.colormap=s.colorMap,delete s.colorMap),"colorMapNegative"in s&&(s.colormapNegative=s.colorMapNegative,delete s.colorMapNegative)}}static async loadFromUrl(t){const s=await(await fetch(t)).arrayBuffer();let r;if(At.isArrayBufferCompressed(s)){const c=await At.decompressArrayBuffer(s);r=JSON.parse(c)}else{const c=new TextDecoder;r=JSON.parse(c.decode(s))}return An.loadFromJSON(r)}static async loadFromFile(t){const n=await At.readFileAsync(t);let s;const r=new An;return At.isArrayBufferCompressed(n)?s=await At.decompressArrayBuffer(n):s=new TextDecoder().decode(n),r.data=JSON.parse(s),r.data.opts.meshThicknessOn2D==="infinity"&&(r.data.opts.meshThicknessOn2D=1/0),r.scene.sceneData={...Za,...r.data.sceneData},An.deserializeMeshDataObjects(r),r}static loadFromJSON(t){const n=new An;Object.assign(n.data,{...t,imageOptionsArray:t.imageOptionsArray??[],encodedImageBlobs:t.encodedImageBlobs??[],labels:t.labels??[],meshOptionsArray:t.meshOptionsArray??[],connectomes:t.connectomes??[],encodedDrawingBlob:t.encodedDrawingBlob??"",previewImageDataURL:t.previewImageDataURL??"",customData:t.customData??"",title:t.title??"untitled"}),n.data.opts={...mi,...t.opts||{}},n.data.opts.meshThicknessOn2D==="infinity"&&(n.data.opts.meshThicknessOn2D=1/0),n.scene.sceneData={...Za,...t.sceneData||{}};const s=t.sceneData||{};return s.clipPlane&&!s.clipPlanes&&(n.scene.sceneData.clipPlanes=[s.clipPlane]),s.clipPlaneDepthAziElev&&!s.clipPlaneDepthAziElevs&&(n.scene.sceneData.clipPlaneDepthAziElevs=[s.clipPlaneDepthAziElev]),t.completedMeasurements&&(n.completedMeasurements=t.completedMeasurements.map(r=>({...r,startMM:gi(r.startMM),endMM:gi(r.endMM)}))),t.completedAngles&&(n.completedAngles=t.completedAngles.map(r=>({...r,firstLineMM:{start:gi(r.firstLineMM.start),end:gi(r.firstLineMM.end)},secondLineMM:{start:gi(r.secondLineMM.start),end:gi(r.secondLineMM.end)}}))),n.data.meshesString&&An.deserializeMeshDataObjects(n),n}static oldloadFromJSON(t){const n=new An;return n.data=t,n.data.opts.meshThicknessOn2D==="infinity"&&(n.data.opts.meshThicknessOn2D=1/0),n.scene.sceneData={...Za,...t.sceneData},An.deserializeMeshDataObjects(n),n}setOptsChangeCallback(t){this._optsChangeCallback=t,this._optsProxy=null}removeOptsChangeCallback(){this._optsChangeCallback=null,this._optsProxy=null}_createOptsProxy(){const t=this.data.opts;this._optsProxy=new Proxy(t,{set:(n,s,r)=>{const c=n[s];return c!==r&&(n[s]=r,this._optsChangeCallback&&typeof s=="string"&&s in mi&&this._optsChangeCallback(s,r,c)),!0},get:(n,s)=>n[s]})}},w4={colormap:"gray",opacity:0,nFrame4D:0,frame4D:0,outlineBorder:0,cal_min:0,cal_max:0,cal_minNeg:0,cal_maxNeg:0,colormapType:0,values:new Array,useNegativeCmap:!1,showLegend:!0},Gs=class yi{constructor(t,n,s="",r=new Uint8Array([255,255,255,255]),c=1,l=!0,d,h=null,u=null,m=null,g=null,A=null,v=!0,y=""){z(this,"id"),z(this,"name"),z(this,"anatomicalStructurePrimary"),z(this,"colorbarVisible"),z(this,"furthestVertexFromOrigin"),z(this,"extentsMin"),z(this,"extentsMax"),z(this,"opacity"),z(this,"visible"),z(this,"meshShaderIndex",0),z(this,"offsetPt0",null),z(this,"colormapInvert",!1),z(this,"fiberGroupColormap",null),z(this,"indexBuffer"),z(this,"vertexBuffer"),z(this,"vao"),z(this,"vaoFiber"),z(this,"pts"),z(this,"tris"),z(this,"layers"),z(this,"type","mesh"),z(this,"data_type"),z(this,"rgba255"),z(this,"fiberLength"),z(this,"fiberLengths"),z(this,"fiberDensity"),z(this,"fiberDither",.1),z(this,"fiberColor","Global"),z(this,"fiberDecimationStride",1),z(this,"fiberSides",5),z(this,"fiberRadius",0),z(this,"fiberOcclusion",0),z(this,"f32PerVertex",5),z(this,"dpsThreshold",NaN),z(this,"fiberMask"),z(this,"colormap"),z(this,"dpg"),z(this,"dps"),z(this,"dpv"),z(this,"groups"),z(this,"hasConnectome",!1),z(this,"connectome"),z(this,"indexCount"),z(this,"vertexCount",1),z(this,"nodeScale",4),z(this,"edgeScale",1),z(this,"legendLineThickness",0),z(this,"showLegend",!0),z(this,"nodeColormap","warm"),z(this,"edgeColormap","warm"),z(this,"nodeColormapNegative"),z(this,"edgeColormapNegative"),z(this,"nodeMinColor"),z(this,"nodeMaxColor"),z(this,"edgeMin"),z(this,"edgeMax"),z(this,"nodes"),z(this,"edges"),z(this,"points"),this.anatomicalStructurePrimary=y,this.name=s,this.colorbarVisible=v,this.id=qh();const w=Xn.getExtents(t);if(this.furthestVertexFromOrigin=w.mxDx,this.extentsMin=w.extentsMin,this.extentsMax=w.extentsMax,this.opacity=c>1?1:c,this.visible=l,this.meshShaderIndex=0,this.indexBuffer=d.createBuffer(),this.vertexBuffer=d.createBuffer(),this.vao=d.createVertexArray(),d.bindVertexArray(this.vao),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,this.indexBuffer),d.bindBuffer(d.ARRAY_BUFFER,this.vertexBuffer),d.enableVertexAttribArray(0),d.enableVertexAttribArray(1),this.f32PerVertex!==7?(d.vertexAttribPointer(0,3,d.FLOAT,!1,20,0),d.vertexAttribPointer(1,4,d.BYTE,!0,20,12),d.enableVertexAttribArray(2),d.vertexAttribPointer(2,4,d.UNSIGNED_BYTE,!0,20,16)):(d.vertexAttribPointer(0,3,d.FLOAT,!1,28,0),d.vertexAttribPointer(1,3,d.FLOAT,!1,28,12),d.enableVertexAttribArray(2),d.vertexAttribPointer(2,4,d.UNSIGNED_BYTE,!0,28,24)),d.bindVertexArray(null),this.vaoFiber=d.createVertexArray(),this.offsetPt0=null,this.hasConnectome=!1,this.colormapInvert=!1,this.fiberGroupColormap=null,this.pts=t,this.layers=[],this.type="mesh",this.tris=n,r[3]<1){this.rgba255=r,this.fiberLength=2,this.fiberDither=.1,this.fiberColor="Global",this.fiberDecimationStride=1,this.fiberMask=[],this.colormap=h,this.dpg=u,this.dps=m,this.dpv=g,this.groups=A,u&&this.initValuesArray(u),m&&this.initValuesArray(m),g&&this.initValuesArray(g),A&&this.initValuesArray(A),this.offsetPt0=new Uint32Array(n),this.tris=new Uint32Array(0),this.updateFibers(d),d.bindVertexArray(this.vaoFiber),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,this.indexBuffer),d.bindBuffer(d.ARRAY_BUFFER,this.vertexBuffer),d.enableVertexAttribArray(0),d.vertexAttribPointer(0,3,d.FLOAT,!1,16,0),d.enableVertexAttribArray(1),d.vertexAttribPointer(1,4,d.UNSIGNED_BYTE,!0,16,12),d.bindVertexArray(null);return}if(h){this.connectome=h,this.hasConnectome=!0;const C=Object.keys(h);for(let S=0,E=C.length;SMath.min(c,l)),r=t[n].vals.reduce((c,l)=>Math.max(c,l));t[n].global_min=s,t[n].global_max=r,t[n].cal_min=s,t[n].cal_max=r}return t}linesToCylinders(t,n,s){function r(I){return lt(I[0],I[1],I[2])}const c=Math.pow(2,32)-1,l=s.length;let d=0,h=0;for(let I=0;I 1 requires f32PerVertex == 5");const A=new Float32Array(m*g),v=new Uint8Array(A.buffer);let y=0,w=ki(),b=ki(),C=ki();const S=Gt();let E=Gt(),M=0;const N=this.fiberRadius;for(let I=0;I=U)&&(S[N]=M[N-1]+M[N]+M[N]+M[N+1]);N=-1,M=S.slice();for(let F=0;F=U)&&(S[N]=M[N-E]+M[N]+M[N]+M[N+E]);const T=E*E;N=-1,M=S.slice();for(let F=0;F=U)&&(S[N]=M[N-T]+M[N]+M[N]+M[T]);return S}h=y(h,r),h=y(h,r);let w=0,b=1/0;const C=r*r*r;for(let S=0;S0){const U=parseInt(y.substring(3));U0){const U=parseInt(y.substring(3));U0){const U=new Uint8ClampedArray(this.groups.length*4),T=new Array(this.groups.length).fill(!1);if(this.fiberGroupColormap){const F=this.fiberGroupColormap;F.A===void 0&&(F.A=Array.from(new Uint8ClampedArray(F.I.length).fill(255)));for(let I=0;I=this.groups.length||F.A[I]<1||(T[B]=!0,B*=4,U[B]=F.R[I],U[B+1]=F.G[I],U[B+2]=F.B[I],U[B+3]=255)}}else if(y.startsWith("dpg")&&this.dpg.length>0){const F=parseInt(y.substring(3)),I=F0){let U=function(T,F){const I=F*(T&255),B=F*(T>>8&255),V=F*(T>>16&255);return I+(B<<8)+(V<<16)};this.createFiberDensityMap();for(let T=0;T2&&this.fiberRadius>0?this.linesToCylinders(t,l,M):(this.indexCount=M.length,t.bindBuffer(t.ARRAY_BUFFER,this.vertexBuffer),t.bufferData(t.ARRAY_BUFFER,Uint32Array.from(d),t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,Uint32Array.from(M),t.STATIC_DRAW))}indexNearestXYZmm(t,n,s){const r=this.pts,c=this.pts.length/3;let l=0,d=1/0,h=0;for(let u=0;u0)for(let n=0;n0)for(let n=0;n0)for(let n=0;n0&&A)b=Math.round(n.opacity*255*Math.pow(w/g,2));else continue;if(w=(w-d)*v,w<0&&n.isTransparentBelowCalMin)continue;w=Math.min(255,Math.max(0,Math.round(w)))*4;const C=y*4;t[C+0]=u[w+0],t[C+1]=u[w+1],t[C+2]=u[w+2],t[C+3]=b}return t}blendColormap(t,n,s,r,c,l,d=!1){const h=this.pts.length/3,u=Math.min(s.opacity,1);function m(E,M,N){return E*(1-N)+M*N}function g(E,M){return Math.min(E+M,255)}const A=d?-1:1,v=Math.min(Math.max(s.frame4D,0),s.nFrame4D-1),y=h*v;let w=r;s.isTransparentBelowCalMin||(w=Number.NEGATIVE_INFINITY),s.colormapType!==0&&(r=Math.min(r,0));const b=255/(c-r);let C=new Array(h).fill(!1);if(s.outlineBorder!==0){const E=new Uint8Array(h).fill(0);for(let M=0;M=w&&(E[M]=1);C=Xn.getClusterBoundaryU8(E,this.tris);for(let M=0;Mr&&s.colormapType===2){let E=Math.round((w-r)*b);E=Math.max(E,1);for(let M=1;M0)for(let u=0;um.cal_max)continue;if(m.outlineBorder===void 0&&(m.outlineBorder=0),m.isAdditiveBlend===void 0&&(m.isAdditiveBlend=!1),m.colormapLabel&&m.colormapLabel.R&&!m.colormapLabel.lut&&(m.colormapLabel=Pt.makeLabelLut(m.colormapLabel,255,m.global_max)),m.colormapLabel&&m.colormapLabel.lut){const v=m.colormapLabel;let y=0;m.colormapLabel.min&&(y=m.colormapLabel.min);let w=v.lut;const b=Math.floor(w.length/4);if(m.atlasValues&&b>0&&b===m.atlasValues.length&&m.colormap){const U=m.atlasValues;let T=!1,F=!0;for(let I=0;IR/255),F=m.colormapLabel.labels[U],I=[0,0,0];let B=0;for(let R=0;R0&&(I[0]/=B,I[1]/=B,I[2]/=B),T[3]===0||!F||F.startsWith("_"))continue;T[3]=1;const V=new pu(F,{textColor:T,bulletScale:1,bulletColor:T,lineWidth:0,lineColor:T,textScale:1,textAlignment:"left",lineTerminator:"none"},I);m.labels.push(V),k.debug("label for mesh layer:",V)}}else delete m.labels;const C=Math.min(Math.max(m.frame4D,0),m.nFrame4D-1),S=r*C,E=new Uint8Array(r*4);let M=0;for(let U=0;U0)for(let u=0;u=n;l--){const d=Math.pow(4,l+1)*(r-2)+2,h=Math.pow(4,l)*(r-2)+2,u=s.length/3,m=Math.pow(4,l)*c;k.info(`order ${l+1} -> ${l} vertices ${d} -> ${h} faces ${u} -> ${m}`);const g=Array.from({length:d},(v,y)=>y+1);for(let v=0;v=s)return k.warn(`Unable to decimate mesh: input order (${s}) must be larger than downsampled order (${n})`),!1;const r=this.pts.length/3,l=Math.pow(4,n)*(12-2)+2;if(this.pts=new Float32Array(this.pts.slice(0,l*3)),this.decimateFaces(s,n),this.layers&&this.layers.length>0)for(let d=0;d"u"){const b=new Float32Array([0,0,0,0,0,0]),C=new Uint32Array([0]);m={pts:b,offsetPt0:C},k.error("Creating empty tracts")}return c[3]=0,new yi(m.pts,m.offsetPt0,n,c,r,l,s,"inferno",m.dpg||null,m.dps||null,m.dpv||null,m.groups)}if(A==="GII")m=await $t.readGII(t);else if(A==="MZ3")m=await $t.readMZ3(t),"positions"in m||k.warn("MZ3 does not have positions (statistical overlay?)");else if(A==="ASC")m=$t.readASC(t);else if(A==="DFS")m=$t.readDFS(t);else if(A==="BYU"||A==="G")m=$t.readGEO(t);else if(A==="GEO")m=$t.readGEO(t,!0);else if(A==="ICO"||A==="TRI")m=$t.readICO(t);else if(A==="OFF")m=$t.readOFF(t);else if(A==="NV")m=$t.readNV(t);else if(A==="OBJ")m=await $t.readOBJ(t);else if(A==="PLY")m=$t.readPLY(t);else if(A==="WRL")m=$t.readWRL(t);else if(A==="X3D")m=$t.readX3D(t);else if(A==="FIB"||A==="VTK"){if(m=$t.readVTK(t),"offsetPt0"in m)return c[3]=0,new yi(m.pts,m.offsetPt0,n,c,r,l,s,"inferno")}else A==="SRF"?m=await $t.readSRF(t):A==="STL"?m=$t.readSTL(t):m=$t.readFreeSurfer(t);if(m.anatomicalStructurePrimary&&(u=m.anatomicalStructurePrimary),m instanceof Float32Array)throw new Error("fatal: unknown mesh type loaded");if(!("positions"in m))throw new Error("positions not loaded");if(!m.indices)throw new Error("indices not loaded");if(h=m.positions,d=m.indices,"rgba255"in m&&m.rgba255.length>0&&(c=m.rgba255),"colors"in m&&m.colors&&m.colors.length===h.length){const b=h.length/3;c=new Uint8Array(b*4);let C=0,S=0;for(let E=0;E0){const b=await $t.readLayer(n,t,w,r,"gray");typeof b>"u"?k.warn("readLayer() failed to convert scalars"):(w.layers.push(b),w.updateMesh(s))}return w}static async loadLayer(t,n){let s=new Uint8Array().buffer;function r(y){const w=window.atob(y),b=w.length,C=new Uint8Array(b);for(let S=0;S-1&&(c=c.slice(0,c.indexOf("?")));let d=.5;"opacity"in t&&(d=t.opacity);let h="warm";"colormap"in t&&(h=t.colormap);let u="winter";"colormapNegative"in t&&(u=t.colormapNegative);let m=!1;"useNegativeCmap"in t&&(m=t.useNegativeCmap);let g=null;"cal_min"in t&&(g=t.cal_min);let A=null;"cal_max"in t&&(A=t.cal_max);const v=await $t.readLayer(c,s,n,d,h,u,m,g,A);v&&n.layers.push(v)}static async loadFromUrl({url:t="",headers:n={},gl:s,name:r="",opacity:c=1,rgba255:l=[255,255,255,255],visible:d=!0,layers:h=[],buffer:u=new ArrayBuffer(0)}={}){let m=t.split("/");if(r===""){try{m=new URL(t).pathname.split("/")}catch{m=t.split("/")}r=m.slice(-1)[0],r.indexOf("?")>-1&&(r=r.slice(0,r.indexOf("?")))}if(t==="")throw Error("url must not be empty");if(!s)throw Error("gl context is null");let g;if(u.byteLength>0)g=u;else{const v=await fetch(t,{headers:n});if(!v.ok)throw Error(v.statusText);g=await v.arrayBuffer()}const A=await this.readMesh(g,r,s,c,new Uint8Array(l),d);if(!h||h.length<1)return A;for(let v=0;v{const r=new FileReader;r.onload=()=>{n(r.result)},r.onerror=s,r.readAsArrayBuffer(t)})}static async loadFromFile({file:t,gl:n,name:s="",opacity:r=1,rgba255:c=[255,255,255,255],visible:l=!0,layers:d=[]}={}){if(!t)throw new Error("file must be set");if(!n)throw new Error("rendering context must be set");const h=await yi.readFileAsync(t),u=await yi.readMesh(h,s,n,r,new Uint8Array(c),l);if(!d||d.length<1)return u;for(let m=0;m({name:Array.isArray(l.comments)&&l.comments.length>0&&"text"in l.comments[0]?l.comments[0].text:"",x:l.coordinates.x,y:l.coordinates.y,z:l.coordinates.z,colorValue:1,sizeValue:1,metadata:l.comments}));return{...Ul,nodeColormap:n,edgeColormap:n,nodes:r,edges:[]}}updateLabels(){const t=this.nodes;if(t&&t.length>0){const n=t.reduce((u,m)=>u.sizeValue>m.sizeValue?u:m).sizeValue;let s,r;if(typeof this.nodeMinColor<"u"&&isFinite(this.nodeMinColor))s=this.nodeMinColor;else{s=t[0].colorValue;for(let u=1;ur&&(r=t[u].colorValue)}const c=Pt.colormap(this.nodeColormap,this.colormapInvert),l=Pt.colormap(this.nodeColormapNegative,this.colormapInvert),d="nodeColormapNegative"in this;let h=this.legendLineThickness?this.legendLineThickness:0;this.showLegend===!1&&(h=0);for(let u=0;uv/255),k.debug("adding label for ",t[u]),t[u].label=new pu(t[u].name,{textColor:A,bulletScale:t[u].sizeValue/n,bulletColor:A,lineWidth:h,lineColor:A,textScale:1,textAlignment:"left",lineTerminator:"none"},[t[u].x,t[u].y,t[u].z]),k.debug("label for node:",t[u].label)}}}addConnectomeNode(t){if(k.debug("adding node",t),!this.nodes)throw new Error("nodes not defined");this.nodes.push(t),this.updateLabels(),this.nodesChanged.dispatchEvent(new CustomEvent("nodeAdded",{detail:{node:t}}))}deleteConnectomeNode(t){const n=this.nodes.indexOf(t),s=this.edges;s&&(this.edges=s.filter(r=>r.first!==n&&r.second!==n)),this.nodes=this.nodes.filter(r=>r!==t),this.updateLabels(),this.updateConnectome(this.gl),this.nodesChanged.dispatchEvent(new CustomEvent("nodeDeleted",{detail:{node:t}}))}updateConnectomeNodeByIndex(t,n){this.nodes[t]=n,this.updateLabels(),this.updateConnectome(this.gl),this.nodesChanged.dispatchEvent(new CustomEvent("nodeChanged",{detail:{node:n}}))}updateConnectomeNodeByPoint(t,n){const s=this.nodes;if(!s)throw new Error("Node to update does not exist");const r=s.find(l=>At.arraysAreEqual([l.x,l.y,l.z],t));if(!r)throw new Error(`Node with point ${t} to update does not exist`);const c=s.findIndex(l=>l===r);this.updateConnectomeNodeByIndex(c,n)}addConnectomeEdge(t,n,s){const r=this.edges;let c=r.find(l=>(l.first===t||l.second===t)&&l.first+l.second===t+n);return c||(c={first:t,second:n,colorValue:s},r.push(c),this.updateConnectome(this.gl),c)}deleteConnectomeEdge(t,n){const s=this.edges,r=s.find(c=>(c.first===t||c.first===n)&&c.first+c.second===t+n);if(r)this.edges=s.filter(c=>c!==r);else throw new Error(`edge between ${t} and ${n} not found`);return this.updateConnectome(this.gl),r}findClosestConnectomeNode(t,n){const s=this.nodes;if(!s||s.length===0)return null;const r=s.map((c,l)=>({node:c,distance:Math.sqrt(Math.pow(c.x-t[0],2)+Math.pow(c.y-t[1],2)+Math.pow(c.z-t[2],2)),index:l})).filter(c=>c.distancec.distance-l.distance);return r.length>0?r[0].node:null}updateConnectome(t){const n=[],s=[],r=[];let c=Pt.colormap(this.nodeColormap,this.colormapInvert),l=Pt.colormap(this.nodeColormapNegative,this.colormapInvert),d="nodeColormapNegative"in this;this.nodeMinColor===void 0&&(this.nodeMinColor=NaN),this.nodeMaxColor===void 0&&(this.nodeMaxColor=NaN),this.edgeMin===void 0&&(this.edgeMin=NaN),this.edgeMax===void 0&&(this.edgeMax=NaN);let h=this.nodeMinColor,u=this.nodeMaxColor;if(!isFinite(h)||!isFinite(h)){const C=this.nodes;h=C[0].colorValue,u=C[0].colorValue;for(let S=0;S0){if(h=this.edgeMin,u=this.edgeMax,!isFinite(h)||!isFinite(h)){h=A[0].colorValue,u=A[0].colorValue;for(let C=0;C1){r[c]=-d+1,c++,s[c]=l,c++;continue}for(;n127||n+2 "+c+" bytes (x"+t/c+")"),s.slice(0,c)}function Wh(i,t){const n=new Uint8Array(i.buffer),s=new Int8Array(n.buffer);let r=0;const c=new Uint8Array(t);let l=0;for(;r{const s=i.length;if(s<1){k.debug("undo bitmaps not loaded");return}if(t--,t<0&&(t=s-1),t>=s&&(t=0),i[t].length<2){k.debug("drawUndo is misbehaving");return}return n=Wh(i[t],n.length),{drawBitmap:n,currentDrawUndoBitmap:t}};function E4(i,t,n){const{dimX:s,dimY:r,dimZ:c}=n;let l;if(i===0)l=c;else if(i===1)l=r;else if(i===2)l=s;else return null;let d=-1,h=-1;for(let u=0;u0){m=!0;break}}else if(i===1)for(let g=0;g0){m=!0;break}}if(m)break}else if(i===2)for(let g=0;g0){m=!0;break}}if(m)break}m&&(d===-1&&(d=u),h=u)}return d===-1||h===-1?null:{first:d,last:h}}function Ih(i,t,n,s){const{dimX:r,dimY:c,dimZ:l}=s;let d;if(t===0){d=new Float32Array(r*c);const h=i*r*c;for(let u=0;u=c&&(s[m+g]=l)}else if(n===1)for(let m=0;m=c&&(s[v]=l)}else if(n===2)for(let m=0;m=c&&(s[v]=l)}else throw new Error("Invalid slice type")}function l2(i,t,n){if(t<3||n<3)return;const s=new Float32Array(i.length);for(let r=0;r0||t[A]>0){const v=T4(d[A],h[A],u[A],l.intensitySigma),y=l.intensityWeight,w=y*v+(1-y)*g,b=1-w;c[A]=i[A]*w+t[A]*b}else c[A]=i[A]*g+t[A]*m}function B4(i,t,n,s,r,c,l,d){const{dimX:h,dimY:u,dimZ:m}=t,g=l.sliceType??0;let A,v,y;if(g===0)A=h,v=u,y=m-1;else if(g===1)A=h,v=m,y=u-1;else if(g===2)A=u,v=m,y=h-1;else throw new Error("Invalid slice type. Must be AXIAL, CORONAL, or SAGITTAL");const w={intensityWeight:l.intensityWeight??.7,binaryThreshold:l.binaryThreshold??.375,intensitySigma:l.intensitySigma??.1,applySmoothingToSlices:l.applySmoothingToSlices??!0,useIntensityGuided:l.useIntensityGuided??!0};if(r!==void 0&&c!==void 0){if(r>=c)throw new Error("Low slice index must be less than high slice index");if(r<0||c>y)throw new Error(`Slice indices out of bounds [0, ${y}]`)}const b=new Map;for(let C=0;C<=y;C++){const S=Ih(C,g,i,t);for(let E=0;E0)if(!b.has(M))b.set(M,{min:C,max:C});else{const N=b.get(M);N.min=Math.min(N.min,C),N.max=Math.max(N.max,C)}}}for(const[C,S]of b){const E=r!==void 0?Math.max(r,S.min):S.min,M=c!==void 0?Math.min(c,S.max):S.max;if(E>=M||M-E<2)continue;const N=Ih(E,g,i,t),U=Ih(M,g,i,t),T=new Float32Array(N.length),F=new Float32Array(U.length);for(let I=0;I 1 as "no clip" sentinel (keeps existing behavior) + if (clipPlane.a > 1.0) { + return 1000.0; // sentinel large distance + } + vec3 n = clipPlane.xyz; + const float EPS = 1e-6; + float nlen = length(n); + if (nlen < EPS) { + return 1000.0; // invalid plane normal + } + // signed plane value: dot(n, p-0.5) + a + float signedDist = dot(n, samplePos.xyz - 0.5) + clipPlane.a; + // perpendicular (Euclidean) distance is |signedDist| / |n| + return abs(signedDist) / nlen; +} + +// see if clip plane trims ray sampling range sampleStartEnd.x..y +void clipSampleRange(in vec3 dir, in vec4 rayStart, in vec4 clipPlane, inout vec2 sampleStartEnd, inout bool hasClip) { + const float CSR_EPS = 1e-6; + // quick exit: no clip plane + if (clipPlane.a > 1.0) + return; + hasClip = true; + // quick exit: empty range + if ((sampleStartEnd.y - sampleStartEnd.x) <= CSR_EPS) + return; + // Which side does the ray start on? (plane eqn: dot(n, p-0.5) + a = 0) + float sampleSide = dot(clipPlane.xyz, rayStart.xyz - 0.5) + clipPlane.a; + bool startsFront = (sampleSide < 0.0); + float dis = - 1.0; + // plane normal dot ray direction + float cdot = dot(dir, clipPlane.xyz); + // avoid division by 0 for near-parallel plne + if (abs(cdot) >= CSR_EPS) + dis = (-clipPlane.a - dot(clipPlane.xyz, rayStart.xyz - 0.5)) / cdot; + if (dis < 0.0 || dis > sampleStartEnd.y + CSR_EPS) { + if (startsFront) + sampleStartEnd = vec2(0.0, 0.0); + return; + } + bool frontface = (cdot > 0.0); + if (frontface) + sampleStartEnd.x = max(sampleStartEnd.x, dis); + else + sampleStartEnd.y = min(sampleStartEnd.y, dis); + // if nothing remains, mark empty + if (sampleStartEnd.y - sampleStartEnd.x <= CSR_EPS) + sampleStartEnd = vec2(0.0, 0.0); +} + +bool skipSample (float pos, vec2 sampleRange) { + return (pos < sampleRange.x || pos > sampleRange.y); +} + +float frac2ndc(vec3 frac) { +//https://stackoverflow.com/questions/7777913/how-to-render-depth-linearly-in-modern-opengl-with-gl-fragcoord-z-in-fragment-sh + vec4 pos = vec4(frac.xyz, 1.0); //fraction + vec4 dim = vec4(vec3(textureSize(volume, 0)), 1.0); + pos = pos * dim; + vec4 shim = vec4(-0.5, -0.5, -0.5, 0.0); + pos += shim; + vec4 mm = transpose(matRAS) * pos; + float z_ndc = (mvpMtx * vec4(mm.xyz, 1.0)).z; + return (z_ndc + 1.0) / 2.0; +}`+vu,xu=`void main() { + if (fColor.x > 2.0) { + fColor = vec4(1.0, 0.0, 0.0, 0.5); + return; + } + fColor = vec4(0.0,0.0,0.0,0.0); + vec4 clipPlaneColorX = clipPlaneColor; + //if (clipPlaneColor.a < 0.0) + // clipPlaneColorX.a = - 1.0; + bool isColorPlaneInVolume = false; + if (clipPlaneColorX.a < 0.0) { + isColorPlaneInVolume = true; + clipPlaneColorX.a = 0.0; + } + //fColor = vec4(vColor.rgb, 1.0); return; + vec3 start = vColor; + gl_FragDepth = 1.0; + vec3 backPosition = GetBackPosition(start); + // fColor = vec4(backPosition, 1.0); return; + vec3 dir = normalize(backPosition - start); + //clipVolumeStart(start, backPosition); + dir = normalize(dir); + float len = length(backPosition - start); + float lenVox = length((texVox * start) - (texVox * backPosition)); + if ((lenVox < 0.5) || (len > 3.0)) { //length limit for parallel rays + return; + } + float sliceSize = len / lenVox; //e.g. if ray length is 1.0 and traverses 50 voxels, each voxel is 0.02 in unit cube + float stepSize = sliceSize; //quality: larger step is faster traversal, but fewer samples + float opacityCorrection = stepSize/sliceSize; + vec4 deltaDir = vec4(dir.xyz * stepSize, stepSize); + vec4 samplePos = vec4(start.xyz, 0.0); //ray position + + vec2 sampleRange = vec2(0.0, len); + bool hasClip = false; + for (int i = 0; i < MAX_CLIP_PLANES; i++) + clipSampleRange(dir, samplePos, clipPlanes[i], sampleRange, hasClip); + bool isClip = (sampleRange.x > 0.0) || ((sampleRange.y < len) && (sampleRange.y > 0.0)); + float stepSizeFast = sliceSize * 1.9; + vec4 deltaDirFast = vec4(dir.xyz * stepSizeFast, stepSizeFast); + if ((isClipCutaway) && (sampleRange.x <= 0.0) && (sampleRange.y >= len)) { + //completely clipped, but ray does not intersect plane + if (hasClip) + samplePos.a = len + 1.0; + else + sampleRange = vec2(0.0, 0.0); + } + if ((!isClipCutaway) && (sampleRange.x >= sampleRange.y)) + samplePos.a = len + 1.0; + while (samplePos.a <= len) { + if (skipSample(samplePos.a, sampleRange) ^^ isClipCutaway) { + samplePos += deltaDirFast; + continue; + } + float val = texture(volume, samplePos.xyz).a; + if (val > 0.01) + break; + samplePos += deltaDirFast; //advance ray position + } + float drawOpacityA = renderDrawAmbientOcclusionXY.y; + if ((samplePos.a >= len) && (((overlays < 1.0) && (drawOpacityA <= 0.0) ) || (backgroundMasksOverlays > 0))) { + if (isClip) + fColor += clipPlaneColorX; + return; + } + fColor = vec4(1.0, 1.0, 1.0, 1.0); + //gl_FragDepth = frac2ndc(samplePos.xyz); //crude due to fast pass resolution + if (samplePos.a > deltaDirFast.a ) + samplePos -= deltaDirFast; + //end: fast pass + vec4 colAcc = vec4(0.0,0.0,0.0,0.0); + vec4 firstHit = vec4(0.0,0.0,0.0,2.0 * len); + const float earlyTermination = 0.95; + float backNearest = len; //assume no hit + float ran = fract(sin(gl_FragCoord.x * 12.9898 + gl_FragCoord.y * 78.233) * 43758.5453); + // clip planes create steep gradients: reduce aliasing with more jitter + if (isClip) + samplePos += deltaDir * ran * 1.41; //jitter ray + else + samplePos += deltaDir * ran; //jitter ray +`,Jl=` + if (firstHit.a < len) { + gl_FragDepth = frac2ndc(firstHit.xyz); + vec4 paqdSample = texture(paqd, samplePos.xyz); + if (paqdSample.a > 0.0) { + //colAcc.rgb = paqdSample.rgb; + float a = max(abs(paqdUniforms[2]), abs(paqdUniforms[3])); + colAcc.rgb = mix(colAcc.rgb, paqdSample.rgb, 0.5 * paqdSample.a * a); + } + if (isClip) { + //shade voxels with clip color + if (clipPlaneColor.a < 0.0) { + float thresh = 4.0 * sliceSize; + float firstHit1 = firstHit.a + deltaDir.a; + if (isClipCutaway) { + float min1 = abs(firstHit1 - sampleRange.y); + float dx = samplePos.a - firstHit1; + if (min1 < thresh) + colAcc.rgb = mix(colAcc.rgb, clipPlaneColorX.rgb, abs(clipPlaneColor.a)); + else if (( colAcc.a > earlyTermination ) && (dx > thresh)) { + min1 = abs(firstHit1 - sampleRange.x); + if (min1 < (thresh * 0.5)) { + colAcc.rgb = mix(colAcc.rgb , clipPlaneColorX.rgb, abs(clipPlaneColor.a)*0.5); + } + + } + } else { + if (abs(firstHit1 - sampleRange.x) < thresh) + colAcc.rgb = mix(colAcc.rgb, clipPlaneColorX.rgb, abs(clipPlaneColor.a)); + } // clipPlaneColor.a < 0.0 + } + //ambient occlusion: make creases dark + float min1 = 1000.0; + float min2 = 1000.0; + // find smallest and second-smallest distances + vec4 firstHit1 = firstHit - deltaDir; + for (int i = 0; i < MAX_CLIP_PLANES; i++) { + float d = distance2Plane(firstHit1, clipPlanes[i]); + if (d < min1) { + min2 = min1; + min1 = d; + } else if (d < min2) { + min2 = d; + } + } + float thresh = 1.2 * sliceSize; + if ((isClipCutaway) && (min2 < thresh) && (sampleRange.x > 0.0)) { + if ((abs(sampleRange.x - firstHit.a) > ( 2.0 * thresh)) && ((abs(sampleRange.y - firstHit.a) > (2.0 * thresh)))) + min2 = thresh; + } + // if second is 0 -> factor 0 (black), if second >= sliceSize -> factor 1 (unchanged) + const float aoFrac = 0.5; + float factor = (1.0 - aoFrac) + aoFrac * clamp(min2 / thresh, 0.0, 1.0); + // linear darkening: multiply color by factor (or use mix(vec3(0), colAcc.rgb, factor)) + colAcc.rgb *= factor; + } + } + colAcc.a = (colAcc.a / earlyTermination) * backOpacity; + fColor = colAcc; + float renderDrawAmbientOcclusionX = renderDrawAmbientOcclusionXY.x; + float drawOpacity = renderDrawAmbientOcclusionXY.y; + if ((overlays < 1.0) && (drawOpacity <= 0.0)) + return; + //overlay pass + samplePos = vec4(start.xyz, 0.0); //ray position + //start: OPTIONAL fast pass: rapid traversal until first hit + stepSizeFast = sliceSize * 1.0; + deltaDirFast = vec4(dir.xyz * stepSizeFast, stepSizeFast); + while (samplePos.a <= len) { + float val = texture(overlay, samplePos.xyz).a; + if (drawOpacity > 0.0) + val = max(val, texture(drawing, samplePos.xyz).r); + if (val > 0.001) + break; + samplePos += deltaDirFast; //advance ray position + } + if (samplePos.a >= len) { + if (isClip && (fColor.a == 0.0)) + fColor += clipPlaneColorX; + return; + } + samplePos -= deltaDirFast; + if (samplePos.a < 0.0) + vec4 samplePos = vec4(start.xyz, 0.0); //ray position + //end: fast pass + float overFarthest = len; + colAcc = vec4(0.0, 0.0, 0.0, 0.0); + + samplePos += deltaDir * ran; //jitter ray + vec4 overFirstHit = vec4(0.0,0.0,0.0,2.0 * len); + if (backgroundMasksOverlays > 0) + samplePos = firstHit; + bool firstDraw = true; + while (samplePos.a <= len) { + vec4 colorSample = texture(overlay, samplePos.xyz); + if ((colorSample.a < 0.01) && (drawOpacity > 0.0)) { + float val = texture(drawing, samplePos.xyz).r; + vec4 draw = drawColor(val, drawOpacity); + if ((draw.a > 0.0) && (firstDraw)) { + firstDraw = false; + float sum = 0.0; + const float mn = 1.0 / 256.0; + const float sampleRadius = 1.1; + float dx = sliceSize * sampleRadius; + vec3 center = samplePos.xyz; + //six neighbors that share a face + sum += min(texture(drawing, center.xyz + cross(vec3(0.0,0.0,+dx), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(0.0,0.0,-dx), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(0.0,+dx,0.0), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(0.0,-dx,0.0), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(+dx,0.0,0.0), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(-dx,0.0,0.0), dir)).r, mn); + //float proportion = (sum / mn) / 6.0; + + //12 neighbors that share an edge + dx = sliceSize * sampleRadius * sqrt(2.0) * 0.5; + sum += min(texture(drawing, center.xyz + cross(vec3(0.0,+dx,+dx), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(+dx,0.0,+dx), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(+dx,+dx,0.0), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(0.0,-dx,-dx), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(-dx,0.0,-dx), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(-dx,-dx,0.0), dir)).r, mn); + + sum += min(texture(drawing, center.xyz + cross(vec3(0.0,+dx,-dx), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(+dx,0.0,-dx), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(+dx,-dx,0.0), dir)).r, mn); + + sum += min(texture(drawing, center.xyz + cross(vec3(0.0,-dx,+dx), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(-dx,0.0,+dx), dir)).r, mn); + sum += min(texture(drawing, center.xyz + cross(vec3(-dx,+dx,0.0), dir)).r, mn); + float proportion = (sum / mn) / 18.0; //proportion of six neighbors is non-zero + + //a high proportion of hits means crevice + //since the AO term adds shadows that darken most voxels, it will result in dark surfaces + //the term brighten adds a little illumination to balance this + // without brighten, only the most extreme ridges will not be darker + const float brighten = 1.2; + vec3 ao = draw.rgb * (1.0 - proportion) * brighten; + draw.rgb = mix (draw.rgb, ao , renderDrawAmbientOcclusionX); + } + colorSample = draw; + } + samplePos += deltaDir; //advance ray position + if (colorSample.a >= 0.01) { + if (overFirstHit.a > len) + overFirstHit = samplePos; + colorSample.a *= renderOverlayBlend; + colorSample.a = 1.0-pow((1.0 - colorSample.a), opacityCorrection); + colorSample.rgb *= colorSample.a; + colAcc= (1.0 - colAcc.a) * colorSample + colAcc; + overFarthest = samplePos.a; + if ( colAcc.a > earlyTermination ) + break; + } + } + //if (samplePos.a >= len) { + if (colAcc.a <= 0.0) { + if (isClip && (fColor.a == 0.0)) + fColor += clipPlaneColorX; + return; + } + if (overFirstHit.a < firstHit.a) + gl_FragDepth = frac2ndc(overFirstHit.xyz); + float overMix = colAcc.a; + float overlayDepth = 0.3; + if (fColor.a <= 0.0) + overMix = 1.0; + else if (((overFarthest) > backNearest)) { + float dx = (overFarthest - backNearest)/1.73; + dx = fColor.a * pow(dx, overlayDepth); + overMix *= 1.0 - dx; + } + fColor.rgb = mix(fColor.rgb, colAcc.rgb, overMix); + fColor.a = max(fColor.a, colAcc.a); +}`,I4=`#version 300 es +#line 215 +#define MAX_CLIP_PLANES 6 +precision highp int; +precision highp float; +uniform vec3 rayDir; +uniform vec3 texVox; +uniform int backgroundMasksOverlays; +uniform vec3 volScale; +uniform vec4 clipPlane; +uniform vec4 clipPlanes[MAX_CLIP_PLANES]; +uniform highp sampler3D volume, overlay; +uniform highp sampler3D paqd; +uniform vec4 paqdUniforms; +uniform float overlays; +uniform float backOpacity; +uniform mat4 mvpMtx; +uniform mat4 matRAS; +uniform vec4 clipPlaneColor; +uniform float renderOverlayBlend; +uniform highp sampler3D drawing; +uniform highp sampler2D colormap; +uniform vec2 renderDrawAmbientOcclusionXY; +in vec3 vColor; +out vec4 fColor; +`+ar+` + void main() { + vec3 start = vColor; + gl_FragDepth = 1.0; + vec3 backPosition = GetBackPosition(start); + vec3 dir = normalize(backPosition - start); + //clipVolumeStart(start, backPosition); + float len = length(backPosition - start); + float lenVox = length((texVox * start) - (texVox * backPosition)); + if ((lenVox < 0.5) || (len > 3.0)) { //length limit for parallel rays + fColor = vec4(0.0,0.0,0.0,0.0); + return; + } + float sliceSize = len / lenVox; //e.g. if ray length is 1.0 and traverses 50 voxels, each voxel is 0.02 in unit cube + float stepSize = sliceSize; //quality: larger step is faster traversal, but fewer samples + float opacityCorrection = stepSize/sliceSize; + vec4 deltaDir = vec4(dir.xyz * stepSize, stepSize); + vec4 samplePos = vec4(start.xyz, 0.0); //ray position + vec4 colAcc = vec4(0.0,0.0,0.0,0.0); + vec4 firstHit = vec4(0.0,0.0,0.0,2.0 * len); + const float earlyTermination = 0.95; + float backNearest = len; //assume no hit + float dis = len; + //check if axial plane is closest + vec4 aClip = vec4(0.0, 0.0, 1.0, (1.0- clipPlane.z) - 0.5); + float adis = (-aClip.a - dot(aClip.xyz, samplePos.xyz-0.5)) / dot(dir,aClip.xyz); + if (adis > 0.0) + dis = min(adis, dis); + //check of coronal plane is closest + vec4 cClip = vec4(0.0, 1.0, 0.0, (1.0- clipPlane.y) - 0.5); + float cdis = (-cClip.a - dot(cClip.xyz, samplePos.xyz-0.5)) / dot(dir,cClip.xyz); + if (cdis > 0.0) + dis = min(cdis, dis); + //check if coronal slice is closest + vec4 sClip = vec4(1.0, 0.0, 0.0, (1.0- clipPlane.x) - 0.5); + float sdis = (-sClip.a - dot(sClip.xyz, samplePos.xyz-0.5)) / dot(dir,sClip.xyz); + if (sdis > 0.0) + dis = min(sdis, dis); + if ((dis > 0.0) && (dis < len)) { + samplePos = vec4(samplePos.xyz+dir * dis, dis); + colAcc = texture(volume, samplePos.xyz); + colAcc.a = earlyTermination; + firstHit = samplePos; + backNearest = min(backNearest, samplePos.a); + } + //the following are only used by overlays + vec4 clipPlaneColorX = clipPlaneColor; + bool isColorPlaneInVolume = false; + bool isClip = false; + bool isClipCutaway = false; + vec2 sampleRange; + // vec4 clipPos = applyClip(dir, samplePos, len, isClip); + float stepSizeFast = sliceSize * 1.9; + vec4 deltaDirFast = vec4(dir.xyz * stepSizeFast, stepSizeFast); + if (samplePos.a < 0.0) + vec4 samplePos = vec4(start.xyz, 0.0); //ray position + float ran = fract(sin(gl_FragCoord.x * 12.9898 + gl_FragCoord.y * 78.233) * 43758.5453); + samplePos += deltaDir * ran; //jitter ray +`+Jl,R4=`#version 300 es +#line 215 +#define MAX_CLIP_PLANES 6 +precision highp int; +precision highp float; +uniform vec3 rayDir; +uniform vec3 texVox; +uniform int backgroundMasksOverlays; +uniform vec3 volScale; +uniform vec4 clipPlane; +uniform vec4 clipPlanes[MAX_CLIP_PLANES]; +uniform bool isClipCutaway; +uniform highp sampler3D volume, overlay; +uniform highp sampler3D paqd; +uniform vec4 paqdUniforms; +uniform float overlays; +uniform float backOpacity; +uniform mat4 mvpMtx; +uniform mat4 matRAS; +uniform vec4 clipPlaneColor; +uniform float renderOverlayBlend; +uniform highp sampler3D drawing; +uniform highp sampler2D colormap; +uniform vec2 renderDrawAmbientOcclusionXY; +in vec3 vColor; +out vec4 fColor; +`+ar+xu+`while (samplePos.a <= len) { + if (skipSample(samplePos.a, sampleRange) ^^ isClipCutaway) { + samplePos += deltaDirFast; + continue; + } + vec4 colorSample = texture(volume, samplePos.xyz); + samplePos += deltaDir; //advance ray position + if (colorSample.a >= 0.01) { + if (firstHit.a > len) + firstHit = samplePos; + // backNearest = min(backNearest, samplePos.a); + colorSample.a = 1.0-pow((1.0 - colorSample.a), opacityCorrection); + colorSample.rgb *= colorSample.a; + colAcc= (1.0 - colAcc.a) * colorSample + colAcc; + if ( colAcc.a > earlyTermination ) + break; + } + } + if (firstHit.a < len) + backNearest = firstHit.a; +`+Jl,$a=192,lm=`#version 300 es +#line 215 +#define MAX_CLIP_PLANES 6 +precision highp int; +precision highp float; +uniform vec3 rayDir; +uniform vec3 texVox; +uniform int backgroundMasksOverlays; +uniform vec3 volScale; +uniform vec4 clipPlane; +uniform vec4 clipPlanes[MAX_CLIP_PLANES]; +uniform bool isClipCutaway; +uniform highp sampler3D volume, overlay; +uniform highp sampler3D paqd; +uniform vec4 paqdUniforms; +uniform float overlays; +uniform float backOpacity; +uniform mat4 mvpMtx; +uniform mat4 normMtx; +uniform mat4 matRAS; +uniform vec4 clipPlaneColor; +uniform float renderOverlayBlend; +uniform highp sampler3D drawing, gradient; +uniform highp sampler2D colormap; +uniform highp sampler2D matCap; +uniform vec2 renderDrawAmbientOcclusionXY; +uniform float gradientAmount; +uniform float silhouettePower; +uniform float gradientOpacity[${$a}]; +in vec3 vColor; +out vec4 fColor; +`,N4=lm+ar+xu+` + float startPos = samplePos.a; + float clipCloseThresh = 5.0 * deltaDir.a; + float clipClose = sampleRange.x; + if (isClipCutaway) + clipClose = sampleRange.y; + if (!isClip) + clipClose = -1.0; + float brighten = 2.0; //modulating makes average intensity darker 0.5 * 0.5 = 0.25 + //vec4 prevGrad = vec4(0.0); + float silhouetteThreshold = 1.0 - silhouettePower; + while (samplePos.a <= len) { + if (skipSample(samplePos.a, sampleRange) ^^ isClipCutaway) { + samplePos += deltaDirFast; + continue; + } + vec4 colorSample = texture(volume, samplePos.xyz); + if (colorSample.a >= 0.0) { + vec4 grad = texture(gradient, samplePos.xyz); + grad.rgb = normalize(grad.rgb*2.0 - 1.0); + //if (grad.a < prevGrad.a) + // grad.rgb = prevGrad.rgb; + //prevGrad = grad; + vec3 n = mat3(normMtx) * grad.rgb; + n.y = - n.y; + vec4 mc = vec4(texture(matCap, n.xy * 0.5 + 0.5).rgb, 1.0) * brighten; + mc = mix(vec4(1.0), mc, gradientAmount); + if (abs(samplePos.a - clipClose) > clipCloseThresh) + colorSample.rgb *= mc.rgb; + if (firstHit.a > len) + firstHit = samplePos; + backNearest = min(backNearest, samplePos.a); + colorSample.a = 1.0-pow((1.0 - colorSample.a), opacityCorrection); + int gradIdx = int(grad.a * ${$a}.0); + colorSample.a *= gradientOpacity[gradIdx]; + float lightNormDot = dot(grad.rgb, rayDir); + // n.b. "lightNormDor" is cosTheta, "silhouettePower" is Fresnel effect exponent + colorSample.a *= pow(1.0 - abs(lightNormDot), silhouettePower); + float viewAlign = abs(lightNormDot); // 0 = perpendicular, 1 = aligned + // linearly map silhouettePower (0..1) to a threshold range, e.g., [1.0, 0.0] + // Cull voxels that are too aligned with the view direction + if (viewAlign > silhouetteThreshold) + colorSample.a = 0.0; + colorSample.rgb *= colorSample.a; + colAcc= (1.0 - colAcc.a) * colorSample + colAcc; + if ( colAcc.a > earlyTermination ) + break; + } + samplePos += deltaDir; //advance ray position + } +`+Jl,V4=lm+ar+xu+` + float startPos = samplePos.a; + //float clipClose = clipPos.a + 3.0 * deltaDir.a; //do not apply gradients near clip plane + float brighten = 2.0; //modulating makes average intensity darker 0.5 * 0.5 = 0.25 + //vec4 prevGrad = vec4(0.0); + while (samplePos.a <= len) { + vec4 colorSample = texture(volume, samplePos.xyz); + if (colorSample.a >= 0.0) { + vec4 grad = texture(gradient, samplePos.xyz); + colorSample.rgb = abs(normalize(grad.rgb*2.0 - 1.0)); + if (firstHit.a > len) + firstHit = samplePos; + backNearest = min(backNearest, samplePos.a); + colorSample.a = 1.0-pow((1.0 - colorSample.a), opacityCorrection); + colorSample.rgb *= colorSample.a; + colAcc= (1.0 - colAcc.a) * colorSample + colAcc; + if ( colAcc.a > earlyTermination ) + break; + } + samplePos += deltaDir; //advance ray position + } +`+Jl,Bl=`#version 300 es +#line 392 +layout(location=0) in vec3 pos; +uniform int axCorSag; +uniform mat4 mvpMtx; +uniform mat4 frac2mm; +uniform float slice; +out vec3 texPos; +void main(void) { + texPos = vec3(pos.x, pos.y, slice); + if (axCorSag > 1) + texPos = vec3(slice, pos.x, pos.y); + else if (axCorSag > 0) + texPos = vec3(pos.x, slice, pos.y); + vec4 mm = frac2mm * vec4(texPos, 1.0); + gl_Position = mvpMtx * mm; +}`,om=`#version 300 es +#line 411 +precision highp int; +precision highp float; +uniform highp sampler3D volume, overlay; +uniform highp sampler3D paqd; +uniform vec4 paqdUniforms; +uniform int backgroundMasksOverlays; +uniform float overlayOutlineWidth; +uniform float overlayAlphaShader; +uniform int axCorSag; +uniform float overlays; +uniform float opacity; +uniform float drawOpacity; +uniform float drawRimOpacity; +uniform bool isAlphaClipDark; +uniform highp sampler3D drawing; +uniform highp sampler2D colormap; +in vec3 texPos; +out vec4 color; +`+vu+` +vec4 blendRGBA(vec4 foreground, vec4 background) { + float alphaOut = foreground.a + background.a * (1.0 - foreground.a); + vec3 colorOut = (foreground.rgb * foreground.a + background.rgb * background.a * (1.0 - foreground.a)) / alphaOut; + return vec4(colorOut, alphaOut); +} +float paqdEaseAlpha(float alpha) { + // t are alpha transitions + // y0 + // t0..t1 -> mix between y0..y1 + // t1..t2 -> mix between y1..y2 + // >t2 -> y2 + float t0 = paqdUniforms[0]; // 0.3; + float t1 = 0.5 * (paqdUniforms[0] + paqdUniforms[1]); // 0.4; + float t2 = paqdUniforms[1]; // 0.9; + float y0 = 0.0; + float y1 = abs(paqdUniforms[2]); // 1.0; + float y2 = abs(paqdUniforms[3]); //0.25; + if (alpha <= t0) { + return y0; + } else if (alpha <= t1) { + return mix(y0, y1, (alpha - t0) / (t1 - t0)); // LERP 0.0 → 1.0 + } else if (alpha <= t2) { + return mix(y1, y2, (alpha - t1) / (t2 - t1)); // LERP 1.0 → 0.2 + } else { + return y2; + } +} + +void main() { + //color = vec4(1.0, 0.0, 1.0, 1.0);return; + vec4 background = texture(volume, texPos); + color = vec4(background.rgb, opacity); + if ((isAlphaClipDark) && (background.a == 0.0)) color.a = 0.0; //FSLeyes clipping range + vec4 ocolor = vec4(0.0); + float overlayAlpha = overlayAlphaShader; + if (overlays > 0.0) { + ocolor = texture(overlay, texPos); + //dFdx for "boxing" issue 435 has aliasing on some implementations (coarse vs fine) + //however, this only identifies 50% of the edges due to aliasing effects + // http://www.aclockworkberry.com/shader-derivative-functions/ + // https://bgolus.medium.com/distinctive-derivative-differences-cce38d36797b + //if ((ocolor.a >= 1.0) && ((dFdx(ocolor.a) != 0.0) || (dFdy(ocolor.a) != 0.0) )) + // ocolor.rbg = vec3(0.0, 0.0, 0.0); + bool isOutlineBelowNotAboveThreshold = true; + if (isOutlineBelowNotAboveThreshold) { + if ((overlayOutlineWidth > 0.0) && (ocolor.a < 1.0)) { //check voxel neighbors for edge + vec3 vx = (overlayOutlineWidth ) / vec3(textureSize(overlay, 0)); + //6 voxel neighbors that share a face + vec3 vxR = vec3(texPos.x+vx.x, texPos.y, texPos.z); + vec3 vxL = vec3(texPos.x-vx.x, texPos.y, texPos.z); + vec3 vxA = vec3(texPos.x, texPos.y+vx.y, texPos.z); + vec3 vxP = vec3(texPos.x, texPos.y-vx.y, texPos.z); + vec3 vxS = vec3(texPos.x, texPos.y, texPos.z+vx.z); + vec3 vxI = vec3(texPos.x, texPos.y, texPos.z-vx.z); + float a = 0.0; + if (axCorSag != 2) { + a = max(a, texture(overlay, vxR).a); + a = max(a, texture(overlay, vxL).a); + } + if (axCorSag != 1) { + a = max(a, texture(overlay, vxA).a); + a = max(a, texture(overlay, vxP).a); + } + if (axCorSag != 0) { + a = max(a, texture(overlay, vxS).a); + a = max(a, texture(overlay, vxI).a); + } + bool isCheckCorners = true; + if (isCheckCorners) { + //12 voxel neighbors that share an edge + vec3 vxRA = vec3(texPos.x+vx.x, texPos.y+vx.y, texPos.z); + vec3 vxLA = vec3(texPos.x-vx.x, texPos.y+vx.y, texPos.z); + vec3 vxRP = vec3(texPos.x+vx.x, texPos.y-vx.y, texPos.z); + vec3 vxLP = vec3(texPos.x-vx.x, texPos.y-vx.y, texPos.z); + vec3 vxRS = vec3(texPos.x+vx.x, texPos.y, texPos.z+vx.z); + vec3 vxLS = vec3(texPos.x-vx.x, texPos.y, texPos.z+vx.z); + vec3 vxRI = vec3(texPos.x+vx.x, texPos.y, texPos.z-vx.z); + vec3 vxLI = vec3(texPos.x-vx.x, texPos.y, texPos.z-vx.z); + vec3 vxAS = vec3(texPos.x, texPos.y+vx.y, texPos.z+vx.z); + vec3 vxPS = vec3(texPos.x, texPos.y-vx.y, texPos.z+vx.z); + vec3 vxAI = vec3(texPos.x, texPos.y+vx.y, texPos.z-vx.z); + vec3 vxPI = vec3(texPos.x, texPos.y-vx.y, texPos.z-vx.z); + + if (axCorSag == 0) { //axial corners + a = max(a, texture(overlay, vxRA).a); + a = max(a, texture(overlay, vxLA).a); + a = max(a, texture(overlay, vxRP).a); + a = max(a, texture(overlay, vxLP).a); + } + if (axCorSag == 1) { //coronal corners + a = max(a, texture(overlay, vxRS).a); + a = max(a, texture(overlay, vxLS).a); + a = max(a, texture(overlay, vxRI).a); + a = max(a, texture(overlay, vxLI).a); + } + if (axCorSag == 2) { //sagittal corners + a = max(a, texture(overlay, vxAS).a); + a = max(a, texture(overlay, vxPS).a); + a = max(a, texture(overlay, vxAI).a); + a = max(a, texture(overlay, vxPI).a); + } + } + if (a >= 1.0) { + ocolor = vec4(0.0, 0.0, 0.0, 1.0); + overlayAlpha = 1.0; + } + } + + } else { + if ((overlayOutlineWidth > 0.0) && (ocolor.a >= 1.0)) { //check voxel neighbors for edge + vec3 vx = (overlayOutlineWidth ) / vec3(textureSize(overlay, 0)); + vec3 vxR = vec3(texPos.x+vx.x, texPos.y, texPos.z); + vec3 vxL = vec3(texPos.x-vx.x, texPos.y, texPos.z); + vec3 vxA = vec3(texPos.x, texPos.y+vx.y, texPos.z); + vec3 vxP = vec3(texPos.x, texPos.y-vx.y, texPos.z); + vec3 vxS = vec3(texPos.x, texPos.y, texPos.z+vx.z); + vec3 vxI = vec3(texPos.x, texPos.y, texPos.z-vx.z); + float a = 1.0; + if (axCorSag != 2) { + a = min(a, texture(overlay, vxR).a); + a = min(a, texture(overlay, vxL).a); + } + if (axCorSag != 1) { + a = min(a, texture(overlay, vxA).a); + a = min(a, texture(overlay, vxP).a); + } + if (axCorSag != 0) { + a = min(a, texture(overlay, vxS).a); + a = min(a, texture(overlay, vxI).a); + } + if (a < 1.0) { + ocolor = vec4(0.0, 0.0, 0.0, 1.0); + overlayAlpha = 1.0; + } + } + } //outline above threshold + } + +`,L4=`#version 300 es +#line 411 +precision highp int; +precision highp float; +uniform highp sampler2D volume, overlay; +uniform int backgroundMasksOverlays; +uniform float overlayOutlineWidth; +uniform float overlayAlphaShader; +uniform int axCorSag; +uniform float overlays; +uniform float opacity; +uniform float drawOpacity; +uniform bool isAlphaClipDark; +uniform highp sampler2D drawing; +uniform highp sampler2D colormap; +in vec3 texPos; +out vec4 color;`+vu+`void main() { + //color = vec4(1.0, 0.0, 1.0, 1.0);return; + vec4 background = texture(volume, texPos.xy); + color = vec4(background.rgb, opacity); + if ((isAlphaClipDark) && (background.a == 0.0)) color.a = 0.0; //FSLeyes clipping range + vec4 dcolor = drawColor(texture(drawing, texPos.xy).r, drawOpacity); + if (dcolor.a > 0.0) { + color.rgb = mix(color.rgb, dcolor.rgb, dcolor.a); + color.a = max(drawOpacity, color.a); + } +}`,cm=` ocolor.a *= overlayAlpha; + float drawV = texture(drawing, texPos).r; + vec4 dcolor = drawColor(drawV, drawOpacity); + if (dcolor.a > 0.0) { + if (drawRimOpacity >= 0.0) { + vec3 vx = 1.0 / vec3(textureSize(drawing, 0)); + //6 voxel neighbors that share a face + vec3 offsetX = dFdx(texPos); // left-right spacing + vec3 offsetY = dFdy(texPos); // up-down spacing + float L = texture(drawing, texPos - offsetX).r; + float R = texture(drawing, texPos + offsetX).r; + float T = texture(drawing, texPos - offsetY).r; + float B = texture(drawing, texPos + offsetY).r; + if (L != drawV || R != drawV || T != drawV || B != drawV) + dcolor.a = drawRimOpacity; + } + color.rgb = mix(color.rgb, dcolor.rgb, dcolor.a); + color.a = max(drawOpacity, color.a); + } + vec4 pcolor = texture(paqd, texPos); + if (pcolor.a > 0.0) { + pcolor.a = paqdEaseAlpha(pcolor.a); + if (pcolor.a > 0.0) { + if (paqdUniforms[3] < 0.0) + ocolor = blendRGBA(pcolor, ocolor); + else + ocolor = blendRGBA(ocolor, pcolor); + } + } + if ((backgroundMasksOverlays > 0) && (background.a == 0.0)) + return; + float a = color.a + ocolor.a * (1.0 - color.a); // premultiplied alpha + if (a == 0.0) return; + color.rgb = mix(color.rgb, ocolor.rgb, ocolor.a / a); + color.a = a; +}`,O4=om+cm,z4=om+` if (ocolor.a > 0.0) { + //https://gamedev.stackexchange.com/questions/102889/is-it-possible-to-convert-vec4-to-int-in-glsl-using-opengl-es + uint alpha = uint(ocolor.a * 255.0); + vec3 xyzFlip = vec3(float((uint(1) & alpha) > uint(0)), float((uint(2) & alpha) > uint(0)), float((uint(4) & alpha) > uint(0))); + //convert from 0 and 1 to -1 and 1 + xyzFlip = (xyzFlip * 2.0) - 1.0; + //https://math.stackexchange.com/questions/1905533/find-perpendicular-distance-from-point-to-line-in-3d + //v1 principle direction of tensor for this voxel + vec3 v1 = ocolor.rgb; + //flips encode polarity to convert from 0..1 to -1..1 (27 bits vs 24 bit precision) + v1 = normalize( v1 * xyzFlip); + vec3 vxl = fract(texPos * vec3(textureSize(volume, 0))) - 0.5; + //vxl coordinates now -0.5..+0.5 so 0,0,0 is origin + vxl.x = -vxl.x; + float t = dot(vxl,v1); + vec3 P = t * v1; + float dx = length(P-vxl); + ocolor.a = 1.0 - smoothstep(0.2,0.25, dx); + //if modulation was applied, use that to scale alpha not color: + ocolor.a *= length(ocolor.rgb); + ocolor.rgb = normalize(ocolor.rgb); + //compute distance one half voxel closer to viewer: + float pan = 0.5; + if (axCorSag == 0) + vxl.z -= pan; + if (axCorSag == 1) + vxl.y -= pan; + if (axCorSag == 2) + vxl.x += pan; + t = dot(vxl,v1); + P = t * v1; + float dx2 = length(P-vxl); + ocolor.rgb += (dx2-dx-(0.5 * pan)) * 1.0; + } +`+cm,Nh=`#version 300 es +#line 480 +precision highp int; +precision highp float; +uniform vec4 lineColor; +out vec4 color; +void main() { + color = lineColor; +}`,P4=`#version 300 es +#line 723 +precision highp int; +precision highp float; + +uniform vec4 lineColor; +uniform vec4 leftTopWidthHeight; +uniform float thickness; // line thickness in pixels +uniform vec2 canvasWidthHeight; + +out vec4 color; + +void main() { + // fragment position in screen coordinates + vec2 fragCoord = gl_FragCoord.xy; + + // canvas height + float canvasHeight = canvasWidthHeight.y; + + // 'top' and 'bottom' to match gl_FragCoord.y coordinate system + float top = canvasHeight - leftTopWidthHeight.y; + float bottom = top - leftTopWidthHeight.w; + + // left and right edges + float left = leftTopWidthHeight.x; + float right = left + leftTopWidthHeight.z; + + bool withinLeft = fragCoord.x >= left && fragCoord.x <= left + thickness; + bool withinRight = fragCoord.x <= right && fragCoord.x >= right - thickness; + bool withinTop = fragCoord.y <= top && fragCoord.y >= top - thickness; + bool withinBottom = fragCoord.y >= bottom && fragCoord.y <= bottom + thickness; + + bool isOutline = withinLeft || withinRight || withinTop || withinBottom; + + if (isOutline) { + color = lineColor; + } else { + discard; + } +}`,k4=`#version 300 es +#line 490 +layout(location=0) in vec3 pos; +uniform vec2 canvasWidthHeight; +uniform vec4 leftTopWidthHeight; +out vec2 vColor; +void main(void) { + //convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1 + vec2 frac; + frac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1 + frac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0 + frac = (frac * 2.0) - 1.0; + gl_Position = vec4(frac, 0.0, 1.0); + vColor = pos.xy; +}`,Y4=`#version 300 es +#line 506 +precision highp int; +precision highp float; +uniform highp sampler2D colormap; +uniform float layer; +in vec2 vColor; +out vec4 color; +void main() { + float nlayer = float(textureSize(colormap, 0).y); + float fmap = (0.5 + layer) / nlayer; + color = vec4(texture(colormap, vec2(vColor.x, fmap)).rgb, 1.0); +}`,o2=`#version 300 es +#line 520 +layout(location=0) in vec3 pos; +uniform vec2 canvasWidthHeight; +uniform vec4 leftTopWidthHeight; +void main(void) { + //convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1 + vec2 frac; + frac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1 + frac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0 + frac = (frac * 2.0) - 1.0; + gl_Position = vec4(frac, 0.0, 1.0); +}`,G4=`#version 300 es +#line 534 +layout(location=0) in vec3 pos; +uniform vec2 canvasWidthHeight; +uniform float thickness; +uniform vec4 startXYendXY; +void main(void) { + vec2 posXY = mix(startXYendXY.xy, startXYendXY.zw, pos.x); + vec2 dir = normalize(startXYendXY.xy - startXYendXY.zw); + posXY += vec2(-dir.y, dir.x) * thickness * (pos.y - 0.5); + posXY.x = (posXY.x) / canvasWidthHeight.x; //0..1 + posXY.y = 1.0 - (posXY.y / canvasWidthHeight.y); //1..0 + gl_Position = vec4((posXY * 2.0) - 1.0, 0.0, 1.0); +}`,H4=`#version 300 es +#line 534 +layout(location=0) in vec3 pos; +uniform vec2 canvasWidthHeight; +uniform float thickness; +uniform vec2 startXY; +uniform vec3 endXYZ; // transformed XYZ point +void main(void) { + vec2 posXY = mix(startXY.xy, endXYZ.xy, pos.x); + vec2 startDiff = endXYZ.xy - startXY.xy; + float startDistance = length(startDiff); + vec2 diff = endXYZ.xy - posXY; + float currentDistance = length(diff); + vec2 dir = normalize(startXY.xy - endXYZ.xy); + posXY += vec2(-dir.y, dir.x) * thickness * (pos.y - 0.5); + posXY.x = (posXY.x) / canvasWidthHeight.x; //0..1 + posXY.y = 1.0 - (posXY.y / canvasWidthHeight.y); //1..0 + float z = endXYZ.z * ( 1.0 - abs(currentDistance/startDistance)); + gl_Position = vec4((posXY * 2.0) - 1.0, z, 1.0); +}`,q4=`#version 300 es +#line 549 +layout(location=0) in vec3 pos; +uniform vec2 canvasWidthHeight; +uniform vec4 leftTopWidthHeight; +out vec2 vUV; +void main(void) { + //convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1 + vec2 frac; + frac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1 + frac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0 + frac = (frac * 2.0) - 1.0; + gl_Position = vec4(frac, 0.0, 1.0); + vUV = vec2(pos.x, 1.0 - pos.y); +}`,X4=`#version 300 es +#line 565 +precision highp int; +precision highp float; +uniform highp sampler2D bmpTexture; +in vec2 vUV; +out vec4 color; +void main() { + color = texture(bmpTexture, vUV); +}`,K4=`#version 300 es +#line 576 +layout(location=0) in vec3 pos; +uniform vec2 canvasWidthHeight; +uniform vec4 leftTopWidthHeight; +uniform vec4 uvLeftTopWidthHeight; +out vec2 vUV; +void main(void) { + //convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1 + vec2 frac; + frac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1 + frac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0 + frac = (frac * 2.0) - 1.0; + gl_Position = vec4(frac, 0.0, 1.0); + vUV = vec2(uvLeftTopWidthHeight.x + (pos.x * uvLeftTopWidthHeight.z), uvLeftTopWidthHeight.y + ((1.0 - pos.y) * uvLeftTopWidthHeight.w) ); +}`,j4=`#version 300 es +#line 593 +precision highp int; +precision highp float; +uniform highp sampler2D fontTexture; +uniform vec4 fontColor; +uniform float screenPxRange; +in vec2 vUV; +out vec4 color; +float median(float r, float g, float b) { + return max(min(r, g), min(max(r, g), b)); +} +void main() { + vec3 msd = texture(fontTexture, vUV).rgb; + float sd = median(msd.r, msd.g, msd.b); + float screenPxDistance = screenPxRange*(sd - 0.5); + float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0); + color = vec4(fontColor.rgb , fontColor.a * opacity); +}`,Q4=`#version 300 es +layout(location=0) in vec3 pos; +uniform vec2 canvasWidthHeight; +uniform vec4 leftTopWidthHeight; +uniform vec4 uvLeftTopWidthHeight; +out vec2 vUV; +void main(void) { + //convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1 + vec2 frac; + frac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1 + frac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0 + frac = (frac * 2.0) - 1.0; + gl_Position = vec4(frac, 0.0, 1.0); + vUV = pos.xy; +}`,Z4=`#version 300 es +precision highp int; +precision highp float; +uniform vec4 circleColor; +uniform float fillPercent; +in vec2 vUV; +out vec4 color; +void main() { + /* Check if the pixel is inside the circle + and color it with a gradient. Otherwise, color it + transparent */ + float distance = length(vUV-vec2(0.5,0.5)); + if ( distance < 0.5 && distance >= (1.0 - fillPercent) / 2.0){ + color = vec4(circleColor.r,circleColor.g,circleColor.b,circleColor.a) ; + }else{ + color = vec4(0.0,0.0,0.0,0.0); + } +} +`,kn=`#version 300 es +#line 613 +precision highp int; +precision highp float; +in vec3 vPos; +out vec2 TexCoord; +void main() { + TexCoord = vPos.xy; + gl_Position = vec4( (vPos.xy-vec2(0.5,0.5)) * 2.0, 0.0, 1.0); +}`,Il=`#version 300 es +uniform highp usampler3D intensityVol; +`,c2=`#version 300 es +uniform highp isampler3D intensityVol; +`,W4=`#version 300 es +uniform highp sampler3D intensityVol; +`,h2=`#line 1042 +precision highp int; +precision highp float; +in vec2 TexCoord; +out vec4 FragColor; +uniform bool isAdditiveBlend; +uniform float coordZ; +uniform float layer; +uniform highp sampler2D colormap; +uniform lowp sampler3D blend3D; +uniform float opacity; +uniform uint activeIndex; +uniform vec4 xyzaFrac; +uniform mat4 mtx; +float textureWidth; +float nlayer; +float layerY; + +vec4 scalar2color(uint idx) { + float fx = (float(idx) + 0.5) / textureWidth; + vec4 clr = texture(colormap, vec2(fx, layerY)).rgba; + if (clr.a > 0.0) + clr.a = 1.0; + clr.a *= opacity; + return clr; +} +void main(void) { + vec4 vx = vec4(TexCoord.x, TexCoord.y, coordZ, 1.0) * mtx; + uint idx = uint(texture(intensityVol, vx.xyz).r); + if (idx == uint(0)) { + if (layer < 1.0) { + FragColor = vec4(0.0, 0.0, 0.0, 0.0); + return; + } + FragColor = texture(blend3D, vec3(TexCoord.xy, coordZ)); + return; + } + textureWidth = float(textureSize(colormap, 0).x); + nlayer = float(textureSize(colormap, 0).y); + layerY = ((2.0 * layer) + 1.5) / nlayer; + //idx = ((idx - uint(1)) % uint(100))+uint(1); + FragColor = scalar2color(idx); + bool isBorder = false; + vx = vec4(TexCoord.x+xyzaFrac.x, TexCoord.y, coordZ, 1.0) * mtx; + uint R = uint(texture(intensityVol, vx.xyz).r); + vx = vec4(TexCoord.x-xyzaFrac.x, TexCoord.y, coordZ, 1.0) * mtx; + uint L = uint(texture(intensityVol, vx.xyz).r); + vx = vec4(TexCoord.x, TexCoord.y+xyzaFrac.y, coordZ, 1.0) * mtx; + uint A = uint(texture(intensityVol, vx.xyz).r); + vx = vec4(TexCoord.x, TexCoord.y-xyzaFrac.y, coordZ, 1.0) * mtx; + uint P = uint(texture(intensityVol, vx.xyz).r); + vx = vec4(TexCoord.x, TexCoord.y, coordZ+xyzaFrac.z, 1.0) * mtx; + uint S = uint(texture(intensityVol, vx.xyz).r); + vx = vec4(TexCoord.x, TexCoord.y, coordZ-xyzaFrac.z, 1.0) * mtx; + uint I = uint(texture(intensityVol, vx.xyz).r); + vec4 centerColor = FragColor; + FragColor.a += scalar2color(R).a; + FragColor.a += scalar2color(L).a; + FragColor.a += scalar2color(A).a; + FragColor.a += scalar2color(P).a; + FragColor.a += scalar2color(S).a; + FragColor.a += scalar2color(I).a; + FragColor.a /= 7.0; + if ((!isBorder) &&(idx == activeIndex)) { + if (centerColor.a > 0.5) + FragColor.a *= 0.4; + else + FragColor.a =0.8; + } + if (xyzaFrac.a != 0.0) { //outline + if ((idx != R) || (idx != L) || (idx != A) || (idx != P) || (idx != S) || (idx != I)) { + isBorder = true; + if (xyzaFrac.a > 0.0) + FragColor.a = xyzaFrac.a; + else + FragColor = vec4(0.0, 0.0, 0.0, 1.0); + } + } + if (layer < 1.0) return; + vec4 prevColor = texture(blend3D, vec3(TexCoord.xy, coordZ)); + // https://en.wikipedia.org/wiki/Alpha_compositing + float aout = FragColor.a + (1.0 - FragColor.a) * prevColor.a; + if (aout <= 0.0) return; + if (isAdditiveBlend) + FragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a)) / aout; + else + FragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a * (1.0 - FragColor.a))) / aout; + FragColor.a = aout; +}`,Vh=`#line 691 +precision highp int; +precision highp float; +in vec2 TexCoord; +out vec4 FragColor; +uniform float coordZ; +uniform float layer; +uniform float scl_slope; +uniform float scl_inter; +uniform float cal_max; +uniform float cal_min; +uniform float cal_maxNeg; +uniform float cal_minNeg; +uniform bool isAlphaThreshold; +uniform bool isColorbarFromZero; +uniform bool isAdditiveBlend; +uniform highp sampler2D colormap; +uniform lowp sampler3D blend3D; +uniform int modulation; +uniform highp sampler3D modulationVol; +uniform float opacity; +uniform mat4 mtx; +void main(void) { + vec4 vx = vec4(TexCoord.xy, coordZ, 1.0) * mtx; + if ((vx.x < 0.0) || (vx.x > 1.0) || (vx.y < 0.0) || (vx.y > 1.0) || (vx.z < 0.0) || (vx.z > 1.0)) { + //set transparent if out of range + //https://webglfundamentals.org/webgl/webgl-3d-textures-repeat-clamp.html + FragColor = texture(blend3D, vec3(TexCoord.xy, coordZ)); + return; + } + float f = (scl_slope * float(texture(intensityVol, vx.xyz).r)) + scl_inter; + float mn = cal_min; + float mx = cal_max; + if ((isAlphaThreshold) || (isColorbarFromZero)) + mn = 0.0; + float r = max(0.00001, abs(mx - mn)); + mn = min(mn, mx); + float txl = mix(0.0, 1.0, (f - mn) / r); + if (f > mn) { //issue1139: survives threshold, so round up to opaque voxel + txl = max(txl, 2.0/256.0); + } + //https://stackoverflow.com/questions/5879403/opengl-texture-coordinates-in-pixel-space + float nlayer = float(textureSize(colormap, 0).y); + //each volume has two color maps: + // (layer*2) = negative and (layer * 2) + 1 = positive + float y = ((2.0 * layer) + 1.5)/nlayer; + FragColor = texture(colormap, vec2(txl, y)).rgba; + //negative colors + mn = cal_minNeg; + mx = cal_maxNeg; + if ((isAlphaThreshold) || (isColorbarFromZero)) + mx = 0.0; + //if ((!isnan(cal_minNeg)) && ( f < mx)) { + if ((cal_minNeg < cal_maxNeg) && ( f < mx)) { + r = max(0.00001, abs(mx - mn)); + mn = min(mn, mx); + txl = 1.0 - mix(0.0, 1.0, (f - mn) / r); + //issue1139: survives threshold, so round up to opaque voxel + txl = max(txl, 2.0/256.0); + y = ((2.0 * layer) + 0.5)/nlayer; + FragColor = texture(colormap, vec2(txl, y)); + } + if (layer > 0.7) + FragColor.a = step(0.00001, FragColor.a); + //if (modulation > 10) + // FragColor.a *= texture(modulationVol, vx.xyz).r; + // FragColor.rgb *= texture(modulationVol, vx.xyz).r; + if (isAlphaThreshold) { + if ((cal_minNeg != cal_maxNeg) && ( f < 0.0) && (f > cal_maxNeg)) + FragColor.a = pow(-f / -cal_maxNeg, 2.0); + else if ((f > 0.0) && (cal_min > 0.0)) + FragColor.a *= pow(f / cal_min, 2.0); //issue435: A = (V/X)**2 + //FragColor.g = 0.0; + } else if (isColorbarFromZero) { + if ((cal_minNeg != cal_maxNeg) && ( f < 0.0) && (f > cal_maxNeg)) + FragColor.a = 0.0; + else if ((f > 0.0) && (cal_min > 0.0) && (f < cal_min)) + FragColor.a *= 0.0; + + } + if (modulation == 1) { + FragColor.rgb *= texture(modulationVol, vx.xyz).r; + } else if (modulation == 2) { + FragColor.a = texture(modulationVol, vx.xyz).r; + } + FragColor.a *= opacity; + if (layer < 1.0) return; + vec4 prevColor = texture(blend3D, vec3(TexCoord.xy, coordZ)); + // https://en.wikipedia.org/wiki/Alpha_compositing + float aout = FragColor.a + (1.0 - FragColor.a) * prevColor.a; + if (aout <= 0.0) return; + if (isAdditiveBlend) + FragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a)) / aout; + else + FragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a * (1.0 - FragColor.a))) / aout; + FragColor.a = aout; +}`,_4=`#line 773 +precision highp int; +precision highp float; +in vec2 TexCoord; +out vec4 FragColor; +uniform float coordZ; +uniform float layer; +uniform float scl_slope; +uniform float scl_inter; +uniform float cal_max; +uniform float cal_min; +uniform highp sampler2D colormap; +uniform lowp sampler3D blend3D; +uniform float opacity; +uniform mat4 mtx; +uniform bool hasAlpha; +uniform int modulation; +uniform highp sampler3D modulationVol; +float textureWidth; +float nlayer; +float layerY; + +vec4 scalar2color(uint idx) { + float fx = (float(idx) + 0.5) / textureWidth; + vec4 clr = texture(colormap, vec2(fx, layerY)).rgba; + if (clr.a > 0.0) + clr.a = 1.0; + clr.a *= opacity; + return clr; +} + +vec4 paqd2color(uvec4 rgba) { + // paqd r: max prob index, g: 2nd index, b: max prob a: 2nd prob + float prob1 = float(rgba.b)/255.0; + float prob2 = float(rgba.a)/255.0; + vec4 clr1 = scalar2color(rgba.r); + vec4 clr2 = scalar2color(rgba.g); + float total = prob1 + prob2; + vec4 clr = vec4(clr1.rgb, total); + // vec4 clr = vec4(clr1.rgb, prob1); + if (total > 0.0) { + clr.rgb = mix(clr2.rgb, clr1.rgb, prob1 / total); + } + return clr; +} +void main(void) { + vec4 vx = vec4(TexCoord.xy, coordZ, 1.0) * mtx; + ivec3 voxelCoord = ivec3(vx.xyz * vec3(textureSize(intensityVol, 0))); + uvec4 rgba = texelFetch(intensityVol, voxelCoord, 0); + FragColor = vec4(0.0, 0.0, 0.0, 0.0); + if (rgba.r > uint(0)) { + textureWidth = float(textureSize(colormap, 0).x); + nlayer = float(textureSize(colormap, 0).y); + layerY = ((2.0 * layer) + 1.5) / nlayer; + FragColor = paqd2color(rgba); + return; + } + // if (layer > 2.0) return; + // FragColor = texture(blend3D, vec3(TexCoord.xy, coordZ)); +}`,J4=`#line 773 +precision highp int; +precision highp float; +in vec2 TexCoord; +out vec4 FragColor; +uniform float coordZ; +uniform float layer; +uniform float scl_slope; +uniform float scl_inter; +uniform float cal_max; +uniform float cal_min; +uniform highp sampler2D colormap; +uniform lowp sampler3D blend3D; +uniform float opacity; +uniform mat4 mtx; +uniform bool hasAlpha; +uniform int modulation; +uniform highp sampler3D modulationVol; +void main(void) { + vec4 vx = vec4(TexCoord.xy, coordZ, 1.0) * mtx; + uvec4 aColor = texture(intensityVol, vx.xyz); + FragColor = vec4(float(aColor.r) / 255.0, float(aColor.g) / 255.0, float(aColor.b) / 255.0, float(aColor.a) / 255.0); + if (modulation == 1) + FragColor.rgb *= texture(modulationVol, vx.xyz).r; + if (!hasAlpha) { + FragColor.a = (FragColor.r * 0.21 + FragColor.g * 0.72 + FragColor.b * 0.07); + //next line: we could binarize alpha, but see rendering of visible human + //FragColor.a = step(0.01, FragColor.a); + } + if (modulation == 2) + FragColor.a = texture(modulationVol, vx.xyz).r; + FragColor.a *= opacity; + if (layer < 1.0) return; + vec4 prevColor = texture(blend3D, vec3(TexCoord.xy, coordZ)); + // https://en.wikipedia.org/wiki/Alpha_compositing + float aout = FragColor.a + (1.0 - FragColor.a) * prevColor.a; + if (aout <= 0.0) return; + FragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a * (1.0 - FragColor.a))) / aout; + FragColor.a = aout; +}`,$4=`#version 300 es +#line 808 +precision highp int; +precision highp float; +in vec3 vPos; +out vec2 TexCoord; +void main() { + TexCoord = vPos.xy; + gl_Position = vec4((vPos.x - 0.5) * 2.0, (vPos.y - 0.5) * 2.0, 0.0, 1.0); +}`,tv=`#version 300 es +#line 829 + precision highp float; + precision highp int; + precision highp isampler3D; + layout(location = 0) out int label; + layout(location = 1) out int strength; + in vec2 TexCoord; + uniform int finalPass; + uniform float coordZ; + uniform lowp sampler3D in3D; + uniform highp isampler3D backTex; // background + uniform highp isampler3D labelTex; // label + uniform highp isampler3D strengthTex; // strength +void main(void) { + vec3 interpolatedTextureCoordinate = vec3(TexCoord.xy, coordZ); + ivec3 size = textureSize(backTex, 0); + ivec3 texelIndex = ivec3(floor(interpolatedTextureCoordinate * vec3(size))); + int background = texelFetch(backTex, texelIndex, 0).r; + label = texelFetch(labelTex, texelIndex, 0).r; + strength = texelFetch(strengthTex, texelIndex, 0).r; + for (int k = -1; k <= 1; k++) { + for (int j = -1; j <= 1; j++) { + for (int i = -1; i <= 1; i++) { + if (i != 0 && j != 0 && k != 0) { + ivec3 neighborIndex = texelIndex + ivec3(i,j,k); + int neighborBackground = texelFetch(backTex, neighborIndex, 0).r; + int neighborStrength = texelFetch(strengthTex, neighborIndex, 0).r; + int strengthCost = abs(neighborBackground - background); + int takeoverStrength = neighborStrength - strengthCost; + if (takeoverStrength > strength) { + strength = takeoverStrength; + label = texelFetch(labelTex, neighborIndex, 0).r; + } + } + } + } + } + if (finalPass < 1) + return; + int ok = 1; + ivec4 labelCount = ivec4(0,0,0,0); + for (int k = -1; k <= 1; k++) + for (int j = -1; j <= 1; j++) + for (int i = -1; i <= 1; i++) { + ivec3 neighborIndex = texelIndex + ivec3(i,j,k); + int ilabel = texelFetch(labelTex, neighborIndex, 0).r; + if ((ilabel < 0) || (ilabel > 3)) + ok = 0; + else + labelCount[ilabel]++; + } + if (ok != 1) { + return; + } + int maxIdx = 0; + for (int i = 1; i < 4; i++) { + if (labelCount[i] > labelCount[maxIdx]) + maxIdx = i; + } + label = maxIdx; +}`,ev=`#version 300 es +layout(location=0) in vec3 pos; +uniform mat4 mvpMtx; +void main(void) { + gl_Position = mvpMtx * vec4(pos, 1.0); +}`,iv=`#version 300 es +precision highp int; +precision highp float; +uniform vec4 surfaceColor; +out vec4 color; +void main() { + color = surfaceColor; +}`,nv=`#version 300 es +layout(location=0) in vec3 pos; +layout(location=1) in vec4 clr; +out vec4 vClr; +uniform mat4 mvpMtx; +void main(void) { + gl_Position = mvpMtx * vec4(pos, 1.0); + vClr = clr; +}`,sv=`#version 300 es +precision highp int; +precision highp float; +in vec4 vClr; +out vec4 color; +uniform float opacity; +void main() { + color = vec4(vClr.rgb, opacity); +}`,Lh=`#version 300 es +layout(location=0) in vec3 pos; +layout(location=1) in vec4 norm; +layout(location=2) in vec4 clr; +uniform mat4 mvpMtx; +//uniform mat4 modelMtx; +uniform mat4 normMtx; +out vec4 vClr; +out vec3 vN; +out vec4 vP; +out vec4 vPc; +void main(void) { + vec3 lightPosition = vec3(0.0, 0.0, -10.0); + vP = vec4(pos, 1.0); + vPc = mvpMtx * vec4(pos, 1.0); + gl_Position = vPc; + vN = normalize((normMtx * vec4(norm.xyz,1.0)).xyz); + //vV = -vec3(modelMtx*vec4(pos,1.0)); + vClr = clr; +}`,av=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +out vec4 color; +vec4 packFloatToVec4i(const float value) { + const vec4 bitSh = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0); + const vec4 bitMsk = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0); + vec4 res = fract(value * bitSh); + res -= res.xxyz * bitMsk; + return res; +} +void main() { + color = packFloatToVec4i(gl_FragCoord.z); +}`,rv=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +out vec4 color; +float stepmix(float edge0, float edge1, float E, float x){ + float T = clamp(0.5 * (x - edge0 + E) / E, 0.0, 1.0); + return mix(edge0, edge1, T); +} +void main() { + vec3 r = vec3(0.0, 0.0, 1.0); + float ambient = 0.3; + float diffuse = 0.6; + float specular = 0.5; + float shininess = 50.0; + vec3 n = normalize(vN); + vec3 lightPosition = vec3(0.0, 10.0, -5.0); + vec3 l = normalize(lightPosition); + float df = max(0.0, dot(n, l)); + float sf = pow(max(dot(reflect(l, n), r), 0.0), shininess); + const float A = 0.1; + const float B = 0.3; + const float C = 0.6; + const float D = 1.0; + float E = fwidth(df); + if (df > A - E && df < A + E) df = stepmix(A, B, E, df); + else if (df > B - E && df < B + E) df = stepmix(B, C, E, df); + else if (df > C - E && df < C + E) df = stepmix(C, D, E, df); + else if (df < A) df = 0.0; + else if (df < B) df = B; + else if (df < C) df = C; + else df = D; + E = fwidth(sf); + if (sf > 0.5 - E && sf < 0.5 + E) + sf = smoothstep(0.5 - E, 0.5 + E, sf); + else + sf = step(0.5, sf); + vec3 a = vClr.rgb * ambient; + vec3 d = max(df, 0.0) * vClr.rgb * diffuse; + color.rgb = a + d + (specular * sf); + color.a = opacity; +}`,lv=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +out vec4 color; +void main() { + vec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix) + float ambient = 0.3; + float diffuse = 0.6; + float specular = 0.25; + float shininess = 10.0; + float PenWidth = 0.6; + vec3 n = normalize(vN); + vec3 lightPosition = vec3(0.0, 10.0, -5.0); + vec3 l = normalize(lightPosition); + float lightNormDot = dot(n, l); + float view = abs(dot(n,r)); //with respect to viewer + if (PenWidth < view) discard; + vec3 a = vClr.rgb * ambient; + vec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse; + float s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess); + color.rgb = a + d + s; + color.a = opacity; +}`,ov=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +out vec4 color; +void main() { + const float thresh = 0.4; + const vec3 viewDir = vec3(0.0, 0.0, -1.0); + vec3 n = normalize(vN); + // use abs() for two-sided lighting, max() for one sided + float cosTheta = abs(dot(n, viewDir)); + // float cosTheta = max(dot(n, viewDir), 0.0); + // optional fresnel equation - adjust exponent + // cosTheta = 1.0 - pow(1.0 - cosTheta, 2.0); + // use step for binary edges, smoothstep for feathered edges + // vec3 d = step(thresh, cosTheta) * vClr.rgb; + vec3 d = smoothstep(thresh - 0.05, thresh + 0.05, cosTheta) * vClr.rgb; + color = vec4(d, opacity); +}`,cv=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +out vec4 color; +void main() { + const float edge0 = 0.1; + const float edge1 = 0.25; + const vec3 viewDir = vec3(0.0, 0.0, -1.0); + vec3 n = normalize(vN); + float cosTheta = abs(dot(n, viewDir)); + float alpha = 1.0 - smoothstep(edge0, edge1, cosTheta); + if (alpha <= 0.0) { + discard; + } + color = vec4(0.0, 0.0, 0.0, opacity * alpha); +}`,hv=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +out vec4 color; +void main() { + vec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix) + float diffuse = 1.0; + float specular = 0.2; + float shininess = 10.0; + vec3 n = normalize(vN); + vec3 lightPosition = vec3(0.0, 0.0, -5.0); + vec3 l = normalize(lightPosition); + float lightNormDot = max(dot(n, l), 0.0); + vec3 d = lightNormDot * vClr.rgb * diffuse; + float s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess); + color = vec4(d + s, opacity); +}`,uv=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +out vec4 color; +void main() { + float diffuse = 1.4; + vec3 l = vec3(0.0, 0.0, -1.0); + float lightNormDot = max(dot(normalize(vN), l), 0.0); + color = vec4(lightNormDot * vClr.rgb * diffuse, opacity); +}`,fv=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +out vec4 color; +void main() { + float specularRGB = 0.7; + float specularWhite = 0.3; + float shininess = 10.0; + float diffuse = 1.0; + vec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix) + vec3 n = normalize(vN); + vec3 l = vec3(0.0, 0.0, -1.0); + float lightNormDot = max(dot(n, l), 0.0); + vec3 d3 = lightNormDot * vClr.rgb * diffuse; + float s = pow(max(dot(reflect(l, n), r), 0.0), shininess); + vec3 s3 = specularRGB * s * vClr.rgb; + s *= specularWhite; + color = vec4(d3 + s3 + s, opacity); +}`,dv=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +in vec4 vPc; +out vec4 color; +void main() { + vec3 n = normalize(vN); + // Compute curvature + vec3 dx = dFdx(n); + vec3 dy = dFdy(n); + vec3 xneg = n - dx; + vec3 xpos = n + dx; + vec3 yneg = n - dy; + vec3 ypos = n + dy; + float depth = length(vPc.xyz); + float curv = (cross(xneg, xpos).y - cross(yneg, ypos).x) / depth; + //at this stage 0.5 for flat, with valleys dark and ridges bright + curv = 1.0 - (curv + 0.5); + //clamp + curv = min(max(curv, 0.0), 1.0); + // easing function + curv = pow(curv, 0.5); + //modulate ambient and diffuse with curvature + vec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix) + float ambient = 0.6; + float diffuse = 0.6; + float specular = 0.2; + float shininess = 10.0; + vec3 lightPosition = vec3(0.0, 10.0, -2.0); + vec3 l = normalize(lightPosition); + float lightNormDot = dot(n, l); + vec3 a = vClr.rgb * ambient * curv; + vec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse; + float s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess); + color = vec4(a + d + s, opacity); +}`,mv=`#version 300 es +precision highp int; +precision highp float; +uniform vec4 sliceMM; +uniform float thickMM ; +in vec4 vClr; +in vec4 vP; // vertex position in mm +out vec4 color; +void main() { + const float LINE_WIDTH_PX = 4.0; // target thickness in pixels + //const float LINE_THRESH_MM = 1.5; // target thickness in pixels + const float TILT_STRENGTH = 1.0; // >0 shrinks ribbon for oblique triangles + // --- signed distances to each orthogonal plane (object space) --- + vec3 d = vP.xyz - sliceMM.xyz; + vec3 ad = abs(d); + // --- derivatives to get pixel-consistent widths (per-axis) --- + vec3 fd = fwidth(vP.xyz); + //minDist is in mm not pixels + float minDist = min(ad.x, min(ad.y, ad.z)); + if (minDist > sliceMM.w) discard; + // --- per-plane obliqueness: use the two in-plane components' fwidth --- + float tiltX = length(fd.yz); // for plane with normal X + float tiltY = length(fd.xz); // for plane with normal Y + float tiltZ = length(fd.xy); // for plane with normal Z + float tfX = clamp(1.0 / (1.0 + TILT_STRENGTH * tiltX), 0.0, 1.0); + float tfY = clamp(1.0 / (1.0 + TILT_STRENGTH * tiltY), 0.0, 1.0); + float tfZ = clamp(1.0 / (1.0 + TILT_STRENGTH * tiltZ), 0.0, 1.0); + // --- half-widths for each plane (apply per-axis tilt factor) --- + vec3 halfWidth; + halfWidth.x = (LINE_WIDTH_PX * 0.5) * fd.x * tfX; + halfWidth.y = (LINE_WIDTH_PX * 0.5) * fd.y * tfY; + halfWidth.z = (LINE_WIDTH_PX * 0.5) * fd.z * tfZ; + // --- smooth alpha for each plane --- + vec3 edgeA = 1.0 - smoothstep(vec3(0.0), halfWidth, ad); + // combine planes (max of X,Y,Z ribbons) + float edgeAlpha = max(edgeA.x, max(edgeA.y, edgeA.z)); + if (edgeAlpha <= 1e-4) discard; // outside ribbons + color = vec4(vClr.rgb, vClr.a * edgeAlpha); +}`,gv=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +out vec4 color; +void main() { + vec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix) + float ambient = 0.35; + float diffuse = 0.5; + float specular = 0.2; + float shininess = 10.0; + vec3 n = normalize(vN); + vec3 lightPosition = vec3(0.0, 10.0, -5.0); + vec3 l = normalize(lightPosition); + float lightNormDot = dot(n, l); + vec3 a = vClr.rgb * ambient; + vec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse; + float s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess); + color = vec4(a + d + s, opacity); +}`,Av=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +uniform sampler2D matCap; +out vec4 color; +void main() { + vec3 n = normalize(vN); + vec2 uv = n.xy * 0.5 + 0.5; + uv.y = 1.0 - uv.y; + vec3 clr = texture(matCap,uv.xy).rgb * vClr.rgb; + color = vec4(clr, opacity); +}`,pv=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +out vec4 color; +void main() { + float ambient = 0.35; + float diffuse = 0.6; + vec3 n = normalize(vN); + vec3 lightPosition = vec3(0.0, 10.0, -5.0); + vec3 l = normalize(lightPosition); + float lightNormDot = dot(n, l); + vec3 a = vClr.rgb * ambient; + vec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse; + color = vec4(a + d, opacity); +}`,vv=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +out vec4 color; +void main() { + vec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix) + float ambient = 0.35; + float diffuse = 0.5; + float specular = 0.2; + float shininess = 10.0; + vec3 n = normalize(vN); + vec3 lightPosition = vec3(0.0, 10.0, -5.0); + vec3 l = normalize(lightPosition); + float lightNormDot = dot(n, l); + vec3 up = vec3(0.0, 1.0, 0.0); + float ax = dot(n, up) * 0.5 + 0.5; //Shreiner et al. (2013) OpenGL Programming Guide, 8th Ed., p 388. ISBN-10: 0321773039 + vec3 upClr = vec3(1.0, 1.0, 0.95); + vec3 downClr = vec3(0.4, 0.4, 0.6); + vec3 a = vClr.rgb * ambient; + a *= mix(downClr, upClr, ax); + vec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse; + float s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess); + color = vec4(a + d + s, opacity); +}`,xv=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +in vec3 vN; +out vec4 color; +//Spherical harmonics constants +const float C1 = 0.429043; +const float C2 = 0.511664; +const float C3 = 0.743125; +const float C4 = 0.886227; +const float C5 = 0.247708; +//Spherical harmonics coefficients +// Ramamoorthi, R., and P. Hanrahan. 2001b. "An Efficient Representation for Irradiance Environment Maps." In Proceedings of SIGGRAPH 2001, pp. 497–500. +// https://github.com/eskimoblood/processingSketches/blob/master/data/shader/shinyvert.glsl +// https://github.com/eskimoblood/processingSketches/blob/master/data/shader/shinyvert.glsl +// Constants for Eucalyptus Grove lighting +const vec3 L00 = vec3( 0.3783264, 0.4260425, 0.4504587); +const vec3 L1m1 = vec3( 0.2887813, 0.3586803, 0.4147053); +const vec3 L10 = vec3( 0.0379030, 0.0295216, 0.0098567); +const vec3 L11 = vec3(-0.1033028, -0.1031690, -0.0884924); +const vec3 L2m2 = vec3(-0.0621750, -0.0554432, -0.0396779); +const vec3 L2m1 = vec3( 0.0077820, -0.0148312, -0.0471301); +const vec3 L20 = vec3(-0.0935561, -0.1254260, -0.1525629); +const vec3 L21 = vec3(-0.0572703, -0.0502192, -0.0363410); +const vec3 L22 = vec3( 0.0203348, -0.0044201, -0.0452180); +vec3 SH(vec3 vNormal) { + vNormal = vec3(vNormal.x,vNormal.z,vNormal.y); + vec3 diffuseColor = C1 * L22 * (vNormal.x * vNormal.x - vNormal.y * vNormal.y) + + C3 * L20 * vNormal.z * vNormal.z + + C4 * L00 - + C5 * L20 + + 2.0 * C1 * L2m2 * vNormal.x * vNormal.y + + 2.0 * C1 * L21 * vNormal.x * vNormal.z + + 2.0 * C1 * L2m1 * vNormal.y * vNormal.z + + 2.0 * C2 * L11 * vNormal.x + + 2.0 * C2 * L1m1 * vNormal.y + + 2.0 * C2 * L10 * vNormal.z; + return diffuseColor; +} +void main() { + vec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix) + float ambient = 0.3; + float diffuse = 0.6; + float specular = 0.1; + float shininess = 10.0; + vec3 n = normalize(vN); + vec3 lightPosition = vec3(0.0, 10.0, -5.0); + vec3 l = normalize(lightPosition); + float s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess); + vec3 a = vClr.rgb * ambient; + vec3 d = vClr.rgb * diffuse * SH(-reflect(n, vec3(l.x, l.y, -l.z)) ); + color = vec4(a + d + s, opacity); +}`,yv=`#version 300 es +layout(location=0) in vec3 pos; +layout(location=1) in vec4 norm; +layout(location=2) in vec4 clr; +uniform mat4 mvpMtx; +//uniform mat4 modelMtx; +uniform mat4 normMtx; +out vec4 vClr; +flat out vec3 vN; +void main(void) { + gl_Position = mvpMtx * vec4(pos, 1.0); + vN = normalize((normMtx * vec4(norm.xyz,1.0)).xyz); + //vV = -vec3(modelMtx*vec4(pos,1.0)); + vClr = clr; +}`,u2=`#version 300 es +precision highp int; +precision highp float; +uniform float opacity; +in vec4 vClr; +flat in vec3 vN; +out vec4 color; +void main() { + vec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix) + float ambient = 0.35; + float diffuse = 0.5; + float specular = 0.2; + float shininess = 10.0; + vec3 n = normalize(vN); + vec3 lightPosition = vec3(0.0, 10.0, -5.0); + vec3 l = normalize(lightPosition); + float lightNormDot = dot(n, l); + vec3 a = vClr.rgb * ambient; + vec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse; + float s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess); + color = vec4(a + d + s, opacity); +}`,wv=`#version 300 es +#line 1260 +#define MAX_CLIP_PLANES 6 +//precision highp int; +precision highp float; +uniform vec3 rayDir; +uniform vec3 volScale; +uniform vec3 texVox; +uniform vec4 clipPlane; +uniform vec4 clipPlanes[MAX_CLIP_PLANES]; +uniform bool isClipCutaway; +uniform highp sampler3D volume, overlay; +uniform highp sampler3D paqd; +uniform vec4 paqdUniforms; +uniform float overlays; +uniform mat4 matRAS; +uniform mat4 mvpMtx; +uniform float drawOpacity, renderOverlayBlend; +uniform highp sampler3D drawing; +uniform highp sampler2D colormap; +uniform int backgroundMasksOverlays; +in vec3 vColor; +out vec4 fColor; +`+ar+` +void main() { + int id = 254; + vec3 start = vColor; + gl_FragDepth = 1.0; + fColor = vec4(0.0, 0.0, 0.0, 0.0); //assume no hit: ID = 0 + float fid = float(id & 255)/ 255.0; + vec3 backPosition = GetBackPosition(start); + vec3 dir = normalize(backPosition - start); + //clipVolumeStart(start, backPosition); + float len = length(backPosition - start); + float lenVox = length((texVox * start) - (texVox * backPosition)); + if ((lenVox < 0.5) || (len > 3.0)) return;//discard; //length limit for parallel rays + float sliceSize = len / lenVox; //e.g. if ray length is 1.0 and traverses 50 voxels, each voxel is 0.02 in unit cube + float stepSize = sliceSize; //quality: larger step is faster traversal, but fewer samples + float opacityCorrection = stepSize/sliceSize; + dir = normalize(dir); + vec4 samplePos = vec4(start.xyz, 0.0); //ray position + bool hasClip = false; + vec2 sampleRange = vec2(0.0, len); + for (int i = 0; i < MAX_CLIP_PLANES; i++) + clipSampleRange(dir, samplePos, clipPlanes[i], sampleRange, hasClip); + bool isClip = (sampleRange.x > 0.0) || ((sampleRange.y < len) && (sampleRange.y > 0.0)); + //vec4 clipPos = applyClip(dir, samplePos, len, isClip); + if (isClip) fColor = vec4(samplePos.xyz, 253.0 / 255.0); //assume no hit: ID = 0 + if ((isClipCutaway) && (sampleRange.x <= 0.0) && (sampleRange.y >= len)) { + //completely clipped, but ray does not intersect plane + if (hasClip) + samplePos.a = len + 1.0; + else + sampleRange = vec2(0.0, 0.0); + } + //start: OPTIONAL fast pass: rapid traversal until first hit + float stepSizeFast = sliceSize * 1.9; + vec4 deltaDirFast = vec4(dir.xyz * stepSizeFast, stepSizeFast); + while (samplePos.a <= len) { + if (skipSample(samplePos.a, sampleRange) ^^ isClipCutaway) { + samplePos += deltaDirFast; + continue; + } + float val = texture(volume, samplePos.xyz).a; + if (val > 0.01) { + fColor = vec4(samplePos.rgb, fid); + gl_FragDepth = frac2ndc(samplePos.xyz); + break; + } + samplePos += deltaDirFast; //advance ray position + } + //end: fast pass + if ((overlays < 1.0) || (backgroundMasksOverlays > 0)) { + return; //background hit, no overlays + } + //overlay pass + len = min(len, samplePos.a); //only find overlay closer than background + samplePos = vec4(start.xyz, 0.0); //ray position + while (samplePos.a <= len) { + float val = texture(overlay, samplePos.xyz).a; + if (val > 0.01) { + fColor = vec4(samplePos.rgb, fid); + gl_FragDepth = frac2ndc(samplePos.xyz); + return; + } + samplePos += deltaDirFast; //advance ray position + } + //if (fColor.a == 0.0) discard; //no hit in either background or overlays + //you only get here if there is a hit with the background that is closer than any overlay +}`,bv=`#version 300 es +// an attribute is an input (in) to a vertex shader. +// It will receive data from a buffer +layout(location=0) in vec3 a_position; +layout(location=1) in vec3 a_color; +// A matrix to transform the positions by +uniform mat4 u_matrix; +out vec3 vColor; +// all shaders have a main function +void main() { + // Multiply the position by the matrix. + vec4 pos = vec4(a_position, 1.0); + gl_Position = u_matrix * vec4(pos); + vColor = a_color; +} +`,Cv=`#version 300 es +precision highp float; +uniform vec4 u_color; +in vec3 vColor; +out vec4 outColor; +void main() { + outColor = vec4(vColor, 1.0); +}`,Sv=`#version 300 es +#line 1359 +precision highp int; +precision highp float; +in vec3 vPos; +out vec2 TexCoord; +void main() { + TexCoord = vPos.xy; + vec2 viewCoord = (vPos.xy - 0.5) * 2.0; + gl_Position = vec4((vPos.xy - 0.5) * 2.0, 0.0, 1.0); +}`,Mv=`#version 300 es +precision highp int; +precision highp float; +in vec2 TexCoord; +out vec4 FragColor; +uniform float coordZ; +uniform lowp sampler3D in3D; +void main(void) { + FragColor = texture(in3D, vec3(TexCoord.xy, coordZ)); +}`,Rl=`#version 300 es +#line 286 +precision highp int; +precision highp float; +in vec3 vPos; +out vec2 TexCoord; +void main() { + TexCoord = vPos.xy; + gl_Position = vec4( (vPos.xy-vec2(0.5,0.5))* 2.0, 0.0, 1.0); +}`,Ev=`#version 300 es +#line 298 +precision highp int; +precision highp float; +in vec2 TexCoord; +out vec4 FragColor; +uniform float coordZ; +uniform float dX; +uniform float dY; +uniform float dZ; +uniform highp sampler3D intensityVol; +void main(void) { + vec3 vx = vec3(TexCoord.xy, coordZ); + vec4 samp = texture(intensityVol,vx+vec3(+dX,+dY,+dZ)); + samp += texture(intensityVol,vx+vec3(+dX,+dY,-dZ)); + samp += texture(intensityVol,vx+vec3(+dX,-dY,+dZ)); + samp += texture(intensityVol,vx+vec3(+dX,-dY,-dZ)); + samp += texture(intensityVol,vx+vec3(-dX,+dY,+dZ)); + samp += texture(intensityVol,vx+vec3(-dX,+dY,-dZ)); + samp += texture(intensityVol,vx+vec3(-dX,-dY,+dZ)); + samp += texture(intensityVol,vx+vec3(-dX,-dY,-dZ)); + FragColor = samp*0.125; +}`,Dv=`#version 300 es +#line 298 +precision highp int; +precision highp float; +in vec2 TexCoord; +out vec4 FragColor; +uniform float coordZ; +uniform float dX; +uniform float dY; +uniform float dZ; +uniform highp sampler3D intensityVol; +void main(void) { + vec3 vx = vec3(TexCoord.xy, coordZ); + vec4 XYZ = texture(intensityVol,vx+vec3(+dX,+dY,+dZ)); + vec4 OYZ = texture(intensityVol,vx+vec3(0.0,+dY,+dZ)); + vec4 xYZ = texture(intensityVol,vx+vec3(-dX,+dY,+dZ)); + vec4 XOZ = texture(intensityVol,vx+vec3(+dX,0.0,+dZ)); + vec4 OOZ = texture(intensityVol,vx+vec3(0.0,0.0,+dZ)); + vec4 xOZ = texture(intensityVol,vx+vec3(-dX,0.0,+dZ)); + vec4 XyZ = texture(intensityVol,vx+vec3(+dX,-dY,+dZ)); + vec4 OyZ = texture(intensityVol,vx+vec3(0.0,-dY,+dZ)); + vec4 xyZ = texture(intensityVol,vx+vec3(-dX,-dY,+dZ)); + + vec4 XYO = texture(intensityVol,vx+vec3(+dX,+dY,0.0)); + vec4 OYO = texture(intensityVol,vx+vec3(0.0,+dY,0.0)); + vec4 xYO = texture(intensityVol,vx+vec3(-dX,+dY,0.0)); + vec4 XOO = texture(intensityVol,vx+vec3(+dX,0.0,0.0)); + vec4 OOO = texture(intensityVol,vx+vec3(0.0,0.0,0.0)); + vec4 xOO = texture(intensityVol,vx+vec3(-dX,0.0,0.0)); + vec4 XyO = texture(intensityVol,vx+vec3(+dX,-dY,0.0)); + vec4 OyO = texture(intensityVol,vx+vec3(0.0,-dY,0.0)); + vec4 xyO = texture(intensityVol,vx+vec3(-dX,-dY,0.0)); + + vec4 XYz = texture(intensityVol,vx+vec3(+dX,+dY,-dZ)); + vec4 OYz = texture(intensityVol,vx+vec3(0.0,+dY,-dZ)); + vec4 xYz = texture(intensityVol,vx+vec3(-dX,+dY,-dZ)); + vec4 XOz = texture(intensityVol,vx+vec3(+dX,0.0,-dZ)); + vec4 OOz = texture(intensityVol,vx+vec3(0.0,0.0,-dZ)); + vec4 xOz = texture(intensityVol,vx+vec3(-dX,0.0,-dZ)); + vec4 Xyz = texture(intensityVol,vx+vec3(+dX,-dY,-dZ)); + vec4 Oyz = texture(intensityVol,vx+vec3(0.0,-dY,-dZ)); + vec4 xyz = texture(intensityVol,vx+vec3(-dX,-dY,-dZ)); + + vec4 blurred = vec4 (0.0, 0.0, 0.0, 0.0); + blurred.r = 2.0*(xOz.r +xOZ.r +xyO.r +xYO.r +xOO.r +XOz.r +XOZ.r +XyO.r +XYO.r +XOO.r) +xyz.r +xyZ.r +xYz.r +xYZ.r +Xyz.r +XyZ.r +XYz.r +XYZ.r; + blurred.g = 2.0*(Oyz.r +OyZ.r +xyO.r +XyO.r +OyO.r +OYz.r +OYZ.r +xYO.r +XYO.r +OYO.r) +xyz.r +Xyz.r +xyZ.r +XyZ.r +xYz.r +XYz.r +xYZ.r +XYZ.r; + blurred.b = 2.0*(Oyz.r +OYz.r +xOz.r +XOz.r +OOz.r +OyZ.r +OYZ.r +xOZ.r +XOZ.r +OOZ.r) +xyz.r +Xyz.r +xYz.r +XYz.r +xyZ.r +XyZ.r +XyZ.r +XYZ.r; + blurred.a = 0.32*(abs(blurred.r)+abs(blurred.g)+abs(blurred.b)); + // 0.0357 = 1/28 to account for weights, rescale to 2**16, + FragColor = 0.0357*blurred; +}`,hm=` + gradientSample.a = log2(gradientSample.r*gradientSample.r + gradientSample.g*gradientSample.g + gradientSample.b*gradientSample.b + 1.922337562475971e-06) + 18.988706873717717; +`,Tv=`#version 300 es +#line 323 +precision highp int; +precision highp float; +in vec2 TexCoord; +out vec4 FragColor; +uniform float coordZ; +uniform float dX; +uniform float dY; +uniform float dZ; +uniform highp sampler3D intensityVol; +void main(void) { + vec3 vx = vec3(TexCoord.xy, coordZ); + //Neighboring voxels 'T'op/'B'ottom, 'A'nterior/'P'osterior, 'R'ight/'L'eft + float TAR = texture(intensityVol,vx+vec3(+dX,+dY,+dZ)).r; + float TAL = texture(intensityVol,vx+vec3(+dX,+dY,-dZ)).r; + float TPR = texture(intensityVol,vx+vec3(+dX,-dY,+dZ)).r; + float TPL = texture(intensityVol,vx+vec3(+dX,-dY,-dZ)).r; + float BAR = texture(intensityVol,vx+vec3(-dX,+dY,+dZ)).r; + float BAL = texture(intensityVol,vx+vec3(-dX,+dY,-dZ)).r; + float BPR = texture(intensityVol,vx+vec3(-dX,-dY,+dZ)).r; + float BPL = texture(intensityVol,vx+vec3(-dX,-dY,-dZ)).r; + vec4 gradientSample = vec4 (0.0, 0.0, 0.0, 0.0); + gradientSample.r = BAR+BAL+BPR+BPL -TAR-TAL-TPR-TPL; + gradientSample.g = TPR+TPL+BPR+BPL -TAR-TAL-BAR-BAL; + gradientSample.b = TAL+TPL+BAL+BPL -TAR-TPR-BAR-BPR; +${hm} + // 0.04242020977371934 = 1/(log2(3*8) - log2(1/(255**2*8))) // 3*8 -> max for 1st order gradient + gradientSample.a *= 0.04242020977371934; + gradientSample.rgb = normalize(gradientSample.rgb); + gradientSample.rgb = (gradientSample.rgb * 0.5)+0.5; + FragColor = gradientSample; +}`,Uv=`#version 300 es +#line 323 +precision highp int; +precision highp float; +in vec2 TexCoord; +out vec4 FragColor; +uniform float coordZ; +uniform float dX; +uniform float dY; +uniform float dZ; +uniform float dX2; +uniform float dY2; +uniform float dZ2; +uniform highp sampler3D intensityVol; +void main(void) { + vec3 vx = vec3(TexCoord.xy, coordZ); + //Neighboring voxels 'T'op/'B'ottom, 'A'nterior/'P'osterior, 'R'ight/'L'eft + vec4 TAR = texture(intensityVol,vx+vec3(+dX,+dY,+dZ)); + vec4 TAL = texture(intensityVol,vx+vec3(+dX,+dY,-dZ)); + vec4 TPR = texture(intensityVol,vx+vec3(+dX,-dY,+dZ)); + vec4 TPL = texture(intensityVol,vx+vec3(+dX,-dY,-dZ)); + vec4 BAR = texture(intensityVol,vx+vec3(-dX,+dY,+dZ)); + vec4 BAL = texture(intensityVol,vx+vec3(-dX,+dY,-dZ)); + vec4 BPR = texture(intensityVol,vx+vec3(-dX,-dY,+dZ)); + vec4 BPL = texture(intensityVol,vx+vec3(-dX,-dY,-dZ)); + vec4 T = texture(intensityVol,vx+vec3(+dX2,0.0,0.0)); + vec4 A = texture(intensityVol,vx+vec3(0.0,+dY2,0.0)); + vec4 R = texture(intensityVol,vx+vec3(0.0,0.0,+dZ2)); + vec4 B = texture(intensityVol,vx+vec3(-dX2,0.0,0.0)); + vec4 P = texture(intensityVol,vx+vec3(0.0,-dY2,0.0)); + vec4 L = texture(intensityVol,vx+vec3(0.0,0.0,-dZ2)); + vec4 gradientSample = vec4 (0.0, 0.0, 0.0, 0.0); + gradientSample.r = -4.0*B.r +8.0*(BAR.r+BAL.r+BPR.r+BPL.r) -8.0*(TAR.r+TAL.r+TPR.r+TPL.r) +4.0*T.r; + gradientSample.g = -4.0*P.g +8.0*(TPR.g+TPL.g+BPR.g+BPL.g) -8.0*(TAR.g+TAL.g+BAR.g+BAL.g) +4.0*A.g; + gradientSample.b = -4.0*L.b +8.0*(TAL.b+TPL.b+BAL.b+BPL.b) -8.0*(TAR.b+TPR.b+BAR.b+BPR.b) +4.0*R.b; +${hm} + gradientSample.a *= 0.0325; + gradientSample.rgb = normalize(gradientSample.rgb); + gradientSample.rgb = (gradientSample.rgb * 0.5)+0.5; + FragColor = gradientSample; +}`,Fv=function(i,t,n){const s=i.createShader(i.VERTEX_SHADER);i.shaderSource(s,t),i.compileShader(s);const r=i.createShader(i.FRAGMENT_SHADER);i.shaderSource(r,n),i.compileShader(r);const c=i.createProgram();if(i.attachShader(c,s),i.attachShader(c,r),i.linkProgram(c),!i.getProgramParameter(c,i.LINK_STATUS))throw console.log(i.getProgramInfoLog(c)),i.getShaderParameter(s,i.COMPILE_STATUS)||console.log("Vertex shader compilation error:",i.getShaderInfoLog(s)),i.getShaderParameter(r,i.COMPILE_STATUS)||console.log("Fragment shader compilation error:",i.getShaderInfoLog(r)),k.error(i.getProgramInfoLog(c)),new Error("Shader failed to link, see console for log");return c},Tt=class{constructor(i,t,n){z(this,"program"),z(this,"uniforms",{}),z(this,"isMatcap"),z(this,"isCrosscut"),this.program=Fv(i,t,n);const s=/uniform[^;]+[ ](\w+);/g,r=/uniform[^;]+[ ](\w+);/,c=t.match(s),l=n.match(s);c&&c.forEach(d=>{const h=d.match(r);this.uniforms[h[1]]=-1}),l&&l.forEach(d=>{const h=d.match(r);this.uniforms[h[1]]=-1});for(const d in this.uniforms)this.uniforms[d]=i.getUniformLocation(this.program,d)}use(i){i.useProgram(this.program)}},f2=(i,t)=>{const n=Math.floor(Math.log(i)/Math.log(10)),s=i/Math.pow(10,n);let r;return t?s<1.5?r=1:s<3?r=2:s<7?r=5:r=10:s<=1?r=1:s<=2?r=2:s<=5?r=5:r=10,r*Math.pow(10,n)};function Bv(i){return new Promise((t,n)=>{let s;i instanceof File?s=Promise.resolve(i):s=new Promise((r,c)=>{i.file(r,c)}),s.then(r=>{const c=new FileReader;c.onload=()=>{typeof c.result=="string"?t(c.result):n(new Error("Expected a string from FileReader.result"))},c.onerror=()=>{n(c.error??new Error("Unknown FileReader error"))},c.readAsDataURL(r)}).catch(r=>n(r))})}function Iv(i){const t=i.hdr.dims,n=i.permRAS,s=t[1]*t[2]*t[3],r=new Int16Array(s),c=[0,0,0];for(let v=0;v<3;v++)for(let y=0;y<3;y++)Math.abs(n[v])-1===y&&(c[y]=v*Math.sign(n[v]));let l=1;const d=[1,1,1],h=[!1,!1,!1];for(let v=0;vc&&([r,c]=[c,r]),[r,c]}function zh(i,t,n){return Math.min(Math.max(i,t),n)}function ne(i,t=[0,1,2]){const n=Gt();return n[0]=i[t[0]],n[1]=i[t[1]],n[2]=i[t[2]],n}function Nv(i){const t=te(1,0,0,0),n=ki();return De(n,t,i),n[0]}function Vv(i,t,n,s){const r=te(i,t,n,1),c=re(s);Pe(c,c),r[0]=r[0]*2-1,r[1]=r[1]*2-1,r[2]=r[2]*2-1;const l=ki();return De(l,r,c),l[3]===0||(l[0]/=l[3],l[1]/=l[3],l[2]/=l[3]),l}var{version:g2}=H5,Yn=["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","WRL","X3D","JCON","JSON"],qa=0,Ph=1,kh=2,Gn=33984,Xa=33985,Nl=33986,A2=33987,Lv=33988,Yh=33989,Vl=33990,gn=33991,zs=33992,p2=33992,v2=33993,x2=33994,Ov=33995,zv=33996,Pv=33997,kv=33998,Yv=33999,y2={filename:"",isSaveDrawing:!1,volumeByIndex:0},Hn,Gv=class{constructor(i=mi){z(this,"loaders",{}),z(this,"dicomLoader",null),z(this,"canvas",null),z(this,"_gl",null),z(this,"isBusy",!1),z(this,"needsRefresh",!1),z(this,"colormapTexture",null),z(this,"colormapLists",[]),z(this,"volumeTexture",null),z(this,"gradientTexture",null),z(this,"gradientTextureAmount",0),z(this,"useCustomGradientTexture",!1),z(this,"renderGradientValues",!1),z(this,"drawTexture",null),z(this,"paqdTexture",null),z(this,"drawUndoBitmaps",[]),z(this,"drawLut",Pt.makeDrawLut("$itksnap")),z(this,"drawOpacity",.8),z(this,"drawRimOpacity",-1),z(this,"clickToSegmentIsGrowing",!1),z(this,"clickToSegmentGrowingBitmap",null),z(this,"clickToSegmentXY",[0,0]),z(this,"renderDrawAmbientOcclusion",.4),z(this,"colorbarHeight",0),z(this,"drawPenLocation",[NaN,NaN,NaN]),z(this,"drawPenAxCorSag",-1),z(this,"drawFillOverwrites",!0),z(this,"drawPenFillPts",[]),z(this,"drawShapeStartLocation",[NaN,NaN,NaN]),z(this,"drawShapePreviewBitmap",null),z(this,"overlayTexture",null),z(this,"overlayTextureID",null),z(this,"sliceMMShader"),z(this,"slice2DShader"),z(this,"sliceV1Shader"),z(this,"orientCubeShader"),z(this,"orientCubeShaderVAO",null),z(this,"rectShader"),z(this,"rectOutlineShader"),z(this,"renderShader"),z(this,"lineShader"),z(this,"line3DShader"),z(this,"passThroughShader"),z(this,"renderGradientShader"),z(this,"renderGradientValuesShader"),z(this,"renderSliceShader"),z(this,"renderVolumeShader"),z(this,"pickingMeshShader"),z(this,"pickingImageShader"),z(this,"colorbarShader"),z(this,"customSliceShader",null),z(this,"fontShader",null),z(this,"fiberShader"),z(this,"fontTexture",null),z(this,"circleShader"),z(this,"matCapTexture",null),z(this,"bmpShader",null),z(this,"bmpTexture",null),z(this,"thumbnailVisible",!1),z(this,"bmpTextureWH",1),z(this,"growCutShader"),z(this,"orientShaderAtlasU",null),z(this,"orientShaderAtlasI",null),z(this,"orientShaderU",null),z(this,"orientShaderI",null),z(this,"orientShaderF",null),z(this,"orientShaderRGBU",null),z(this,"orientShaderPAQD",null),z(this,"surfaceShader",null),z(this,"blurShader",null),z(this,"sobelBlurShader",null),z(this,"sobelFirstOrderShader",null),z(this,"sobelSecondOrderShader",null),z(this,"genericVAO",null),z(this,"unusedVAO",null),z(this,"crosshairs3D",null),z(this,"DEFAULT_FONT_GLYPH_SHEET",a2),z(this,"DEFAULT_FONT_METRICS",r2),z(this,"fontMetrics"),z(this,"fontMets",null),z(this,"fontPx",12),z(this,"legendFontScaling",1),z(this,"backgroundMasksOverlays",0),z(this,"overlayOutlineWidth",0),z(this,"overlayAlphaShader",1),z(this,"position"),z(this,"extentsMin"),z(this,"extentsMax"),z(this,"resizeObserver",null),z(this,"resizeEventListener",null),z(this,"canvasObserver",null),z(this,"syncOpts",{"3d":!1,"2d":!1,zoomPan:!1,cal_min:!1,cal_max:!1,clipPlane:!1,gamma:!1,sliceType:!1,crosshair:!1}),z(this,"readyForSync",!1),z(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,windowX:0,windowY:0,activeDragMode:null,activeDragButton:null,angleFirstLine:[0,0,0,0],angleState:"none",activeClipPlaneIndex:0}),ks(this,Hn,null),z(this,"back",null),z(this,"overlays",[]),z(this,"deferredVolumes",[]),z(this,"deferredMeshes",[]),z(this,"furthestVertexFromOrigin",100),z(this,"volScale",[]),z(this,"vox",[]),z(this,"mousePos",[0,0]),z(this,"screenSlices",[]),z(this,"cuboidVertexBuffer"),z(this,"otherNV",null),z(this,"volumeObject3D",null),z(this,"pivot3D",[0,0,0]),z(this,"furthestFromPivot",10),z(this,"currentClipPlaneIndex",0),z(this,"lastCalled",new Date().getTime()),z(this,"selectedObjectId",-1),z(this,"CLIP_PLANE_ID",1),z(this,"VOLUME_ID",254),z(this,"DISTANCE_FROM_CAMERA",-.54),z(this,"graph",{LTWH:[0,0,640,480],opacity:0,vols:[0],autoSizeMultiplanar:!1,normalizeValues:!1,isRangeCalMinMax:!1}),z(this,"customLayout",[]),z(this,"meshShaders",[{Name:"Phong",Frag:gv},{Name:"Matte",Frag:pv},{Name:"Harmonic",Frag:xv},{Name:"Hemispheric",Frag:vv},{Name:"Crevice",Frag:dv},{Name:"Edge",Frag:hv},{Name:"Diffuse",Frag:uv},{Name:"Outline",Frag:lv},{Name:"Specular",Frag:fv},{Name:"Toon",Frag:rv},{Name:"Flat",Frag:u2},{Name:"Matcap",Frag:Av},{Name:"Rim",Frag:ov},{Name:"Silhouette",Frag:cv},{Name:"Crosscut",Frag:mv}]),z(this,"dragModes",{contrast:1,measurement:2,angle:7,none:0,pan:3,slicer3D:4,callbackOnly:5}),z(this,"sliceTypeAxial",0),z(this,"sliceTypeCoronal",1),z(this,"sliceTypeSagittal",2),z(this,"sliceTypeMultiplanar",3),z(this,"sliceTypeRender",4),z(this,"onDragRelease",()=>{}),z(this,"onMouseUp",()=>{}),z(this,"onLocationChange",()=>{}),z(this,"onIntensityChange",()=>{}),z(this,"onClickToSegment",()=>{}),z(this,"onImageLoaded",()=>{}),z(this,"onMeshLoaded",()=>{}),z(this,"onFrameChange",()=>{}),z(this,"onError",()=>{}),z(this,"onColormapChange",()=>{}),z(this,"onInfo",()=>{}),z(this,"onWarn",()=>{}),z(this,"onDebug",()=>{}),z(this,"onVolumeAddedFromUrl",()=>{}),z(this,"onVolumeWithUrlRemoved",()=>{}),z(this,"onVolumeUpdated",()=>{}),z(this,"onMeshAddedFromUrl",()=>{}),z(this,"onMeshAdded",()=>{}),z(this,"onMeshWithUrlRemoved",()=>{}),z(this,"onZoom3DChange",()=>{}),z(this,"onAzimuthElevationChange",()=>{}),z(this,"onClipPlaneChange",()=>{}),z(this,"onCustomMeshShaderAdded",()=>{}),z(this,"onMeshShaderChanged",()=>{}),z(this,"onMeshPropertyChanged",()=>{}),z(this,"onDicomLoaderFinishedWithImages",()=>{}),z(this,"onDocumentLoaded",()=>{}),z(this,"onOptsChange",()=>{}),z(this,"document",new Bh),z(this,"mediaUrlMap",new Map),z(this,"initialized",!1),z(this,"currentDrawUndoBitmap");for(const t in i)typeof i[t]=="function"?this[t]=i[t]:this.opts[t]=mi[t]===void 0?mi[t]:i[t];this.opts.forceDevicePixelRatio===0?this.uiData.dpr=window.devicePixelRatio||1:this.opts.forceDevicePixelRatio<0?this.uiData.dpr=1:this.uiData.dpr=this.opts.forceDevicePixelRatio,this.currentDrawUndoBitmap=this.opts.maxDrawUndoBitmaps,this.opts.drawingEnabled&&this.createEmptyDrawing(),this.opts.thumbnail.length>0&&(this.thumbnailVisible=!0),k.setLogLevel(this.opts.logLevel),this.document.setOptsChangeCallback((t,n,s)=>{this.onOptsChange(t,n,s)})}get scene(){return this.document.scene}get opts(){return this.document.opts}get sliceMosaicString(){return this.document.opts.sliceMosaicString||""}set sliceMosaicString(i){this.document.opts.sliceMosaicString=i}get isAlphaClipDark(){return this.document.opts.isAlphaClipDark}set isAlphaClipDark(i){this.document.opts.isAlphaClipDark=i}cleanup(){this.resizeEventListener&&(window.removeEventListener("resize",this.resizeEventListener),this.resizeEventListener=null),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.canvasObserver&&(this.canvasObserver.disconnect(),this.canvasObserver=null),dt(this,Hn)&&(dt(this,Hn).abort(),pn(this,Hn,null)),this.document.removeOptsChangeCallback()}get volumes(){return this.document.volumes}set volumes(i){this.document.volumes=i}get meshes(){return this.document.meshes}set meshes(i){this.document.meshes=i}get drawBitmap(){return this.document.drawBitmap}set drawBitmap(i){this.document.drawBitmap=i}get volScaleMultiplier(){return this.scene.volScaleMultiplier}set volScaleMultiplier(i){this.setScale(i)}async saveScene(i="niivue.png"){function t(s,r){const c=document.createElement("a");document.body.appendChild(c),c.style.display="none";const l=window.URL.createObjectURL(s);c.href=l,c.download=r,c.click(),c.remove()}const n=this.canvas;if(!n)throw new Error("canvas not defined");this.drawScene(),n.toBlob(s=>{s&&(i===""&&(i=`niivue-screenshot-${new Date().toString()}.png`,i=i.replace(/\s/g,"_")),t(s,i))})}async attachTo(i,t=null){return await this.attachToCanvas(document.getElementById(i),t),k.debug("attached to element with id: ",i),this}async attachToCanvas(i,t=null){return this.canvas=i,t===null&&(t=navigator.hardwareConcurrency>6,k.debug("AntiAlias ",t," Threads ",navigator.hardwareConcurrency)),this.gl=this.canvas.getContext("webgl2",{alpha:!0,antialias:t}),this.uiData.max2D=this.gl.getParameter(this.gl.MAX_TEXTURE_SIZE),this.uiData.max3D=this.gl.getParameter(this.gl.MAX_3D_TEXTURE_SIZE),k.info("NIIVUE VERSION ",g2),k.debug(`Max texture size 2D: ${this.uiData.max2D} 3D: ${this.uiData.max3D}`),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,this.resizeEventListener=()=>{requestAnimationFrame(()=>{this.resizeListener()})},window.addEventListener("resize",this.resizeEventListener),this.resizeObserver=new ResizeObserver(()=>{requestAnimationFrame(()=>{this.resizeListener()})}),this.resizeObserver.observe(this.canvas.parentElement),this.canvasObserver=new MutationObserver(n=>{for(const s of n)if(s.type==="childList"&&s.removedNodes.length>0&&Array.from(s.removedNodes).includes(this.canvas)){this.cleanup();break}}),this.canvasObserver.observe(this.canvas.parentElement,{childList:!0})),this.opts.interactive&&this.registerInteractions(),await this.init(),this.drawScene(),this}syncWith(i,t={"2d":!0,"3d":!0}){i instanceof Array||(i=[i]),this.otherNV=i,this.syncOpts={...t}}broadcastTo(i,t={"2d":!0,"3d":!0}){i instanceof Array||(i=[i]),this.otherNV=i,this.syncOpts=t}doSync3d(i){i.scene.renderAzimuth=this.scene.renderAzimuth,i.scene.renderElevation=this.scene.renderElevation,i.scene.volScaleMultiplier=this.scene.volScaleMultiplier}doSync2d(i){const t=this.frac2mm(this.scene.crosshairPos);i.scene.crosshairPos=i.mm2frac(t),i.scene.pan2Dxyzmm=xn(this.scene.pan2Dxyzmm)}doSyncGamma(i){const t=this.scene.gamma,n=i.scene.gamma;t!==n&&i.setGamma(t)}doSyncZoomPan(i){i.scene.pan2Dxyzmm=xn(this.scene.pan2Dxyzmm)}doSyncCrosshair(i){const t=this.frac2mm(this.scene.crosshairPos);i.scene.crosshairPos=i.mm2frac(t)}doSyncCalMin(i){this.volumes[0].cal_min!==i.volumes[0].cal_min&&(i.volumes[0].cal_min=this.volumes[0].cal_min,i.updateGLVolume())}doSyncCalMax(i){this.volumes[0].cal_max!==i.volumes[0].cal_max&&(i.volumes[0].cal_max=this.volumes[0].cal_max,i.updateGLVolume())}doSyncSliceType(i){i.setSliceType(this.opts.sliceType)}doSyncClipPlane(i){i.setClipPlane(this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex])}sync(){if(!(!this.gl||!this.otherNV||typeof this.otherNV>"u")&&this.gl.canvas.matches(":focus"))for(let i=0;in===t[s])}textSizePoints(){this.opts.textHeight>=0&&(k.warn("textHeight is deprecated (use fontMinPx and fontSizeScaling)"),this.opts.fontMinPx=this.opts.textHeight*217,this.opts.fontSizeScaling=.4,this.opts.textHeight=-1);const i=this.uiData.dpr||1,t=this.opts.fontMinPx,n=this.gl.canvas.width/i,s=this.gl.canvas.height/i,r=n*s,c=800*600,l=Math.max(r/c,1),d=Math.pow(l,this.opts.fontSizeScaling),h=t*d*i;this.fontPx=h,k.debug(`${n.toFixed(0)}x${s.toFixed(0)} pts (dpi=${i}) => areaScale=${l.toFixed(2)}, scale=${d.toFixed(2)}, minPx=${this.opts.fontMinPx} fontScale=${this.opts.fontSizeScaling} fontPx=${h.toFixed(2)}`)}resizeListener(){if(!(!this.canvas||!this.gl)){if(!this.opts.isResizeCanvas){this.opts.forceDevicePixelRatio>=0&&k.warn("this.opts.forceDevicePixelRatio requires isResizeCanvas"),this.drawScene();return}this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.display="block",this.opts.forceDevicePixelRatio===0?this.uiData.dpr=window.devicePixelRatio||1:this.opts.forceDevicePixelRatio<0?this.uiData.dpr=1:this.uiData.dpr=this.opts.forceDevicePixelRatio,k.debug("devicePixelRatio: "+this.uiData.dpr),"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.textSizePoints(),this.drawScene()}}getRelativeMousePosition(i,t){if(t=t||i.target,!t)return;const n=t.getBoundingClientRect();return{x:i.clientX-n.left,y:i.clientY-n.top}}getNoPaddingNoBorderCanvasRelativeMousePosition(i,t){return t=t||i.target,this.getRelativeMousePosition(i,t)}mouseContextMenuListener(i){i.preventDefault()}mouseDownListener(i){if(this.uiData.mousedown=!0,this.eventInBounds(i))this.opts.bounds&&(this.opts.showBoundsBorder=!0);else{this.opts.showBoundsBorder=!1,this.drawScene();return}i.preventDefault(),this.drawPenLocation=[NaN,NaN,NaN],this.drawPenAxCorSag=-1,this.drawShapeStartLocation=[NaN,NaN,NaN];const t=this.getNoPaddingNoBorderCanvasRelativeMousePosition(i,this.gl.canvas);if(this.opts.dragMode===7&&this.uiData.angleState==="drawing_second_line"||(this.setDragStart(t.x,t.y),this.setDragEnd(t.x,t.y)),k.debug("mouse down"),k.debug(i),!t)return;const[n,s]=[t.x*this.uiData.dpr,t.y*this.uiData.dpr];this.opts.clickToSegment&&(this.clickToSegmentXY=[n,s]);const r=this.getLabelAtPoint([n,s]);if(r){if(r.onClick){r.onClick(r,i);return}for(const c of this.meshes){if(c.type!=="connectome"){if(Array.isArray(r.points)&&r.points.length===3&&r.points.every(Number.isFinite)){const[l,d,h]=r.points;this.scene.crosshairPos=this.mm2frac([l,d,h]),this.updateGLVolume()}continue}for(const l of c.nodes)l.label===r&&(this.scene.crosshairPos=this.mm2frac([l.x,l.y,l.z]),this.updateGLVolume())}}this.uiData.clickedTile=this.tileIndex(n,s),i.button===qa&&i.shiftKey?(this.uiData.mouseButtonCenterDown=!0,this.setActiveDragMode(qa,!0,i.ctrlKey),this.handleMouseAction(this.uiData.activeDragMode,i,t)):i.button===qa?(this.uiData.mouseButtonLeftDown=!0,this.setActiveDragMode(qa,!1,i.ctrlKey),this.handleMouseAction(this.uiData.activeDragMode,i,t)):i.button===kh?(this.uiData.mouseButtonRightDown=!0,this.setActiveDragMode(kh,i.shiftKey,i.ctrlKey),this.handleMouseAction(this.uiData.activeDragMode,i,t)):i.button===Ph&&(this.uiData.mouseButtonCenterDown=!0,this.setActiveDragMode(Ph,i.shiftKey,i.ctrlKey),this.handleMouseAction(this.uiData.activeDragMode,i,t)),this.drawScene()}getMouseButtonDragMode(i,t,n){const s=this.opts.mouseEventConfig;return i===qa?s?.leftButton?t&&s.leftButton.withShift!==void 0?s.leftButton.withShift:n&&s.leftButton.withCtrl!==void 0?s.leftButton.withCtrl:s.leftButton.primary:n?8:this.opts.dragModePrimary:i===kh?s?.rightButton!==void 0?s.rightButton:this.opts.dragMode:i===Ph?s?.centerButton!==void 0?s.centerButton:this.opts.dragMode:this.opts.dragMode}getTouchDragMode(i){const t=this.opts.touchEventConfig;return i?t?.doubleTouch??this.opts.dragMode:t?.singleTouch??this.opts.dragModePrimary}setActiveDragMode(i,t,n){this.uiData.activeDragMode=this.getMouseButtonDragMode(i,t,n),this.uiData.activeDragButton=i}getCurrentDragMode(){return this.uiData.activeDragMode!==null?this.uiData.activeDragMode:this.opts.dragMode}clearActiveDragMode(){this.uiData.activeDragMode=null,this.uiData.activeDragButton=null}handleMouseAction(i,t,n){if(i===8)this.mouseDown(n.x,n.y),this.mouseClick(n.x,n.y);else if(i===9)this.uiData.windowX=t.x,this.uiData.windowY=t.y;else{if(this.mousePos=[n.x*this.uiData.dpr,n.y*this.uiData.dpr],i===0)return;if(i===7)if(this.uiData.angleState==="none")this.uiData.angleState="drawing_first_line";else if(this.uiData.angleState==="drawing_second_line"){const s=[n.x*this.uiData.dpr,n.y*this.uiData.dpr],r=this.tileIndex(s[0],s[1]);let c={sliceIndex:-1,sliceType:0,slicePosition:0};if(r>=0&&r=0&&h[0]>=0&&u[0]>=0&&m[0]>=0){const g=this.frac2mm(d),A=this.frac2mm(h),v=this.frac2mm(u),y=this.frac2mm(m),w={firstLineMM:{start:lt(g[0],g[1],g[2]),end:lt(A[0],A[1],A[2])},secondLineMM:{start:lt(v[0],v[1],v[2]),end:lt(y[0],y[1],y[2])},sliceIndex:c.sliceIndex,sliceType:c.sliceType,slicePosition:c.slicePosition,angle:this.calculateAngleBetweenLines(this.uiData.angleFirstLine,l)};this.document.completedAngles.push(w)}this.resetAngleMeasurement(),this.uiData.angleState="complete",this.drawScene();return}else this.uiData.angleState==="complete"&&(this.resetAngleMeasurement(),this.uiData.angleState="drawing_first_line");this.setDragStart(n.x,n.y),this.uiData.isDragging||(this.uiData.pan2DxyzmmAtMouseDown=xn(this.scene.pan2Dxyzmm)),this.uiData.isDragging=!0,this.uiData.dragClipPlaneStartDepthAziElev=this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex]}}calculateMinMaxVoxIdx(i){if(i.length>2)throw new Error("array must not contain more than two values");return[Math.floor(Math.min(i[0],i[1])),Math.floor(Math.max(i[0],i[1]))]}calculateNewRange({volIdx:i=0}={}){if(this.opts.sliceType===4&&this.sliceMosaicString.length<1||this.uiData.dragStart[0]===this.uiData.dragEnd[0]&&this.uiData.dragStart[1]===this.uiData.dragEnd[1])return;let t=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]);if(t[0]<0)return;const n=this.frac2vox(t,i);if(t=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]),t[0]<0)return;const s=this.frac2vox(t,i);let r=-Number.MAX_VALUE,c=Number.MAX_VALUE;const l=this.calculateMinMaxVoxIdx([n[0],s[0]]),d=this.calculateMinMaxVoxIdx([n[1],s[1]]),h=this.calculateMinMaxVoxIdx([n[2],s[2]]);n[0]-s[0]===0?l[1]=n[0]+1:n[1]-s[1]===0?d[1]=n[1]+1:n[2]-s[2]===0&&(h[1]=n[2]+1);const u=this.volumes[i].hdr,m=this.volumes[i].img;if(!u||!m)return;const g=u.dims[1],A=u.dims[2];for(let w=h[0];wm[M]&&(c=m[M]),r=r)return;const v=d2(u,c),y=d2(u,r);this.volumes[i].cal_min=v,this.volumes[i].cal_max=y,this.onIntensityChange(this.volumes[i])}generateMouseUpCallback(i,t){const n=this.tileIndex(this.uiData.dragStart[0],this.uiData.dragStart[1]),s=this.tileIndex(this.uiData.dragEnd[0],this.uiData.dragEnd[1]);let r=-1;n===s&&(r=s);let c=-1;r>=0&&(c=this.screenSlices[r].axCorSag);const l=this.frac2mm(i),d=this.frac2mm(t),h=Gt();Nd(h,lt(l[0],l[1],l[2]),lt(d[0],d[1],d[2]));const u=tr(h),m=this.frac2vox(i),g=this.frac2vox(t);this.onDragRelease({fracStart:i,fracEnd:t,voxStart:m,voxEnd:g,mmStart:l,mmEnd:d,mmLength:u,tileIdx:r,axCorSag:c})}mouseUpListener(){this.uiData.mousedown=!1;function i(r){return Object.prototype.toString.call(r).indexOf("Function")>-1}const t={mouseButtonRightDown:this.uiData.mouseButtonRightDown,mouseButtonCenterDown:this.uiData.mouseButtonCenterDown,isDragging:this.uiData.isDragging,mousePos:this.mousePos,fracPos:this.canvasPos2frac(this.mousePos)};this.uiData.mouseButtonRightDown=!1;const n=this.uiData.mouseButtonCenterDown;this.uiData.mouseButtonCenterDown=!1,this.uiData.mouseButtonLeftDown=!1;const s=this.getCurrentDragMode();if(this.drawPenFillPts.length>0?this.drawPenFilled():this.opts.drawingEnabled&&!isNaN(this.drawPenLocation[0])?this.drawAddUndoBitmap():this.opts.drawingEnabled&&!isNaN(this.drawShapeStartLocation[0])&&(this.opts.penType===1||this.opts.penType===2)&&(this.opts.penValue===0?this.drawAddUndoBitmap():this.drawAddUndoBitmap(this.drawFillOverwrites),this.drawShapePreviewBitmap=null),this.drawPenLocation=[NaN,NaN,NaN],this.drawPenAxCorSag=-1,this.drawShapeStartLocation=[NaN,NaN,NaN],this.drawShapePreviewBitmap&&(this.drawBitmap=this.drawShapePreviewBitmap,this.drawShapePreviewBitmap=null,this.refreshDrawing(!0,!1)),i(this.onMouseUp)&&this.onMouseUp(t),this.uiData.isDragging){if(this.uiData.isDragging=!1,s===7){if(this.uiData.angleState==="drawing_first_line"){this.uiData.angleFirstLine=[this.uiData.dragStart[0],this.uiData.dragStart[1],this.uiData.dragEnd[0],this.uiData.dragEnd[1]],this.uiData.angleState="drawing_second_line",this.uiData.isDragging=!0,this.drawScene();return}if(this.uiData.angleState==="drawing_second_line"){this.uiData.angleState="complete",this.clearActiveDragMode(),this.drawScene();return}}s===5&&this.drawScene();const r=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]),c=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);if(this.generateMouseUpCallback(r,c),s===6){this.clearActiveDragMode();return}if(s===1){if(n){this.clearActiveDragMode();return}if(this.uiData.dragStart[0]===this.uiData.dragEnd[0]&&this.uiData.dragStart[1]===this.uiData.dragEnd[1]){this.clearActiveDragMode();return}this.calculateNewRange({volIdx:0}),this.refreshLayers(this.volumes[0],0)}if(s===2){const l=this.getCurrentSliceInfo(),d=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]),h=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);if(d[0]>=0&&h[0]>=0){const u=this.frac2mm(d),m=this.frac2mm(h);this.document.completedMeasurements.push({startMM:lt(u[0],u[1],u[2]),endMM:lt(m[0],m[1],m[2]),sliceIndex:l.sliceIndex,sliceType:l.sliceType,slicePosition:l.slicePosition,distance:rp(lt(u[0],u[1],u[2]),lt(m[0],m[1],m[2]))})}this.clearActiveDragMode(),this.drawScene();return}}this.clearActiveDragMode(),this.drawScene()}checkMultitouch(i){if(this.uiData.touchdown&&!this.uiData.multiTouchGesture){const t=this.canvas.getBoundingClientRect();this.mouseDown(i.touches[0].clientX-t.left,i.touches[0].clientY-t.top),this.mouseClick(i.touches[0].clientX-t.left,i.touches[0].clientY-t.top)}}touchStartListener(i){i.preventDefault(),this.uiData.touchTimer||(this.uiData.touchTimer=setTimeout(()=>{this.resetBriCon(i)},this.opts.longTouchTimeout)),this.uiData.touchdown=!0,this.uiData.currentTouchTime=new Date().getTime();const t=this.uiData.currentTouchTime-this.uiData.lastTouchTime;if(t0){this.uiData.doubleTouch=!0,this.setDragStart(i.targetTouches[0].clientX-i.target.getBoundingClientRect().left,i.targetTouches[0].clientY-i.target.getBoundingClientRect().top),this.resetBriCon(i),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&&i.touches.length<2?this.uiData.multiTouchGesture=!1:this.uiData.multiTouchGesture=!0,setTimeout(this.checkMultitouch.bind(this),1,i)}touchEndListener(i){if(i.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.getCurrentDragMode()===1&&(this.calculateNewRange(),this.refreshLayers(this.volumes[0],0));const t=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]),n=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);this.generateMouseUpCallback(t,n)}this.mouseUpListener()}windowingHandler(i,t,n=0){const s=this.uiData.windowX,r=this.uiData.windowY;let c=this.volumes[0].cal_min,l=this.volumes[0].cal_max;const d=this.volumes[0].global_min,h=this.volumes[0].global_max;tr&&(c-=1,l-=1),i>s?(c-=1,l+=1):ih&&(l=h),c>l&&(c=l-1),this.volumes[n].cal_min=c,this.volumes[n].cal_max=l,this.refreshLayers(this.volumes[n],0),this.uiData.windowX=i,this.uiData.windowY=t}mouseLeaveListener(){this.clickToSegmentIsGrowing&&(k.debug("Mouse left canvas, stopping clickToSegment preview."),this.clickToSegmentIsGrowing=!1,this.refreshDrawing(!0,!1)),this.opts.drawingEnabled&&!isNaN(this.drawPenLocation[0])&&(k.debug("Mouse left canvas during drawing, resetting pen state."),this.drawPenLocation=[NaN,NaN,NaN],this.drawPenAxCorSag=-1,this.drawPenFillPts=[]),this.opts.drawingEnabled&&!isNaN(this.drawShapeStartLocation[0])&&(k.debug("Mouse left canvas during shape drawing, resetting shape state."),this.drawShapeStartLocation=[NaN,NaN,NaN],this.drawShapePreviewBitmap&&(this.drawBitmap=this.drawShapePreviewBitmap,this.drawShapePreviewBitmap=null,this.refreshDrawing(!0,!1))),(this.uiData.isDragging||this.uiData.mousedown)&&(k.debug("Mouse left canvas during drag, resetting drag state."),this.uiData.isDragging=!1,this.uiData.mouseButtonLeftDown=!1,this.uiData.mouseButtonCenterDown=!1,this.uiData.mouseButtonRightDown=!1,this.uiData.mousedown=!1,this.drawScene()),this.mousePos=[-1,-1]}mouseMoveListener(i){this.uiData.mousedown&&this.drawScene();const t=this.getNoPaddingNoBorderCanvasRelativeMousePosition(i,this.gl.canvas);if(t){if(!this.eventInBounds(i)){this.updateMousePos(t.x,t.y);return}if(this.uiData.mousedown){const n=t.x*this.uiData.dpr,s=t.y*this.uiData.dpr;if(this.tileIndex(n,s)!==this.uiData.clickedTile)return;const c=this.getCurrentDragMode();if(c===8){this.mouseMove(t.x,t.y),this.mouseClick(t.x,t.y),this.drawScene(),this.uiData.prevX=this.uiData.currX,this.uiData.prevY=this.uiData.currY;return}if(c===9){this.windowingHandler(t.x,t.y),this.drawScene(),this.uiData.prevX=this.uiData.currX,this.uiData.prevY=this.uiData.currY;return}this.setDragEnd(t.x,t.y),this.drawScene(),this.uiData.prevX=this.uiData.currX,this.uiData.prevY=this.uiData.currY}else if(this.getCurrentDragMode()===7&&this.uiData.angleState==="drawing_second_line"){const n=this.getNoPaddingNoBorderCanvasRelativeMousePosition(i,this.gl.canvas);if(!n)return;this.setDragEnd(n.x,n.y),this.drawScene()}else if(!this.uiData.mousedown&&this.opts.clickToSegment){const n=this.getNoPaddingNoBorderCanvasRelativeMousePosition(i,this.gl.canvas);if(!n)return;const s=n.x*this.uiData.dpr,r=n.y*this.uiData.dpr;this.mousePos=[s,r];const c=this.tileIndex(s,r);c>=0&&this.opts.drawingEnabled&&this.screenSlices[c].axCorSag<=2&&(this.clickToSegmentXY=[s,r],this.clickToSegmentIsGrowing=!0,this.doClickToSegment({x:s,y:r,tileIndex:c}))}}}resetBriCon(i=null){if(this.uiData.isDragging)return;if(!this.eventInBounds(i)){this.opts.showBoundsBorder=!1;return}let t=!1;this.opts.sliceType===4&&(t=!0);let n=0,s=0;if(i!==null&&("targetTouches"in i?(n=i.targetTouches[0].clientX-i.target.getBoundingClientRect().left,s=i.targetTouches[0].clientY-i.target.getBoundingClientRect().top):(n=i.offsetX,s=i.offsetY),n*=this.uiData.dpr,s*=this.uiData.dpr,this.inRenderTile(n,s)>=0&&(t=!0)),t){this.uiData.mouseDepthPicker=!0,this.drawScene(),this.drawScene();return}this.getCurrentDragMode()!==4&&(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(i,t){i*=this.uiData.dpr,t*=this.uiData.dpr,this.uiData.dragStart[0]=i,this.uiData.dragStart[1]=t}setDragEnd(i,t){i*=this.uiData.dpr,t*=this.uiData.dpr,this.uiData.dragEnd[0]=i,this.uiData.dragEnd[1]=t}touchMoveListener(i){if(this.uiData.touchdown&&i.touches.length<2){const t=this.canvas.getBoundingClientRect();if(this.uiData.isDragging||(this.uiData.pan2DxyzmmAtMouseDown=xn(this.scene.pan2Dxyzmm)),this.uiData.isDragging=!0,this.uiData.doubleTouch&&this.uiData.isDragging){this.setDragEnd(i.targetTouches[0].clientX-i.target.getBoundingClientRect().left,i.targetTouches[0].clientY-i.target.getBoundingClientRect().top),this.drawScene();return}const n=this.getTouchDragMode(!1);n===8?(this.mouseClick(i.touches[0].clientX-t.left,i.touches[0].clientY-t.top),this.mouseMove(i.touches[0].clientX-t.left,i.touches[0].clientY-t.top)):n===9&&(this.windowingHandler(i.touches[0].pageX,i.touches[0].pageY),this.drawScene())}else this.handlePinchZoom(i)}handlePinchZoom(i){if(i.targetTouches.length===2&&i.changedTouches.length===2){const t=Math.hypot(i.touches[0].pageX-i.touches[1].pageX,i.touches[0].pageY-i.touches[1].pageY),n=this.canvas.getBoundingClientRect();this.mousePos=[i.touches[0].clientX-n.left,i.touches[0].clientY-n.top],tthis.opts.keyDebounceTime){const s=this.cycleActiveClipPlane();console.log("Active clip plane cycled to:",s),console.log("clip planes",this.scene.clipPlanes),this.lastCalled=t}if(i.code===this.opts.clipPlaneHotKey){if(n>this.opts.keyDebounceTime){switch(this.currentClipPlaneIndex=(this.currentClipPlaneIndex+1)%7,this.currentClipPlaneIndex){case 0:this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex]=[2,0,0];break;case 1:this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex]=[0,270,0];break;case 2:this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex]=[0,90,0];break;case 3:this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex]=[0,0,0];break;case 4:this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex]=[0,180,0];break;case 5:this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex]=[0,0,-90];break;case 6:this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex]=[0,0,90];break}this.setClipPlane(this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex])}this.lastCalled=t}else if(i.code===this.opts.viewModeHotKey){const s=new Date().getTime();s-this.lastCalled>this.opts.keyDebounceTime&&(this.setSliceType((this.opts.sliceType+1)%5),this.lastCalled=s)}this.drawScene()}keyDownListener(i){if(!this.cursorInBounds()){this.opts.showBoundsBorder=!1,this.drawScene();return}i.code==="KeyH"&&this.opts.sliceType===4?this.setRenderAzimuthElevation(this.scene.renderAzimuth-1,this.scene.renderElevation):i.code==="KeyL"&&this.opts.sliceType===4?this.setRenderAzimuthElevation(this.scene.renderAzimuth+1,this.scene.renderElevation):i.code==="KeyJ"&&this.opts.sliceType===4?this.setRenderAzimuthElevation(this.scene.renderAzimuth,this.scene.renderElevation+1):i.code==="KeyK"&&this.opts.sliceType===4?this.setRenderAzimuthElevation(this.scene.renderAzimuth,this.scene.renderElevation-1):i.code==="KeyH"&&this.opts.sliceType!==4?this.moveCrosshairInVox(-1,0,0):i.code==="KeyL"&&this.opts.sliceType!==4?this.moveCrosshairInVox(1,0,0):i.code==="KeyU"&&this.opts.sliceType!==4&&i.ctrlKey?this.moveCrosshairInVox(0,0,1):i.code==="KeyD"&&this.opts.sliceType!==4&&i.ctrlKey?this.moveCrosshairInVox(0,0,-1):i.code==="KeyJ"&&this.opts.sliceType!==4?this.moveCrosshairInVox(0,-1,0):i.code==="KeyK"&&this.opts.sliceType!==4?this.moveCrosshairInVox(0,1,0):i.code==="KeyM"&&this.opts.sliceType!==4?(this.opts.dragMode++,this.opts.dragMode>=4&&(this.opts.dragMode=0),k.info("drag mode changed to ",am[this.opts.dragMode])):i.code==="ArrowLeft"?this.setFrame4D(this.volumes[0].id,this.volumes[0].frame4D-1):i.code==="ArrowRight"?this.setFrame4D(this.volumes[0].id,this.volumes[0].frame4D+1):i.code==="Slash"&&i.shiftKey&&alert(`NIIVUE VERSION: ${g2}`),this.drawScene()}wheelListener(i){if(this.thumbnailVisible||this.opts.sliceMosaicString.length>0)return;if(this.eventInBounds(i))this.opts.bounds&&(this.opts.showBoundsBorder=!0);else{this.opts.showBoundsBorder=!1,this.drawScene();return}i.preventDefault(),i.stopPropagation();const t=this.uiData.dragStart.reduce((h,u)=>h+u,0),n=this.uiData.dragEnd.reduce((h,u)=>h+u,0),s=t>0&&n>0;if(this.getCurrentDragMode()===6&&s){const h=i.deltaY>0?1:-1;this.uiData.dragStart[0]=0?this.generateMouseUpCallback(this.screenXY2TextureFrac(this.uiData.dragStart[0],this.uiData.dragStart[1],u),this.screenXY2TextureFrac(this.uiData.dragEnd[0],this.uiData.dragEnd[1],u)):k.warn("Could not generate drag release callback for ROI selection: Invalid tile index.");return}let r=i.deltaY<0?-.01:.01;if(this.opts.invertScrollDirection&&(r=-r),this.opts.clickToSegment){r<0?(this.opts.clickToSegmentPercent-=.01,this.opts.clickToSegmentPercent=Math.max(this.opts.clickToSegmentPercent,0)):(this.opts.clickToSegmentPercent+=.01,this.opts.clickToSegmentPercent=Math.min(this.opts.clickToSegmentPercent,1));const h=this.clickToSegmentXY[0],u=this.clickToSegmentXY[1],m=this.tileIndex(h,u);m>=0&&this.screenSlices[m].axCorSag<=2&&(k.debug(`Adjusting clickToSegment threshold: ${this.opts.clickToSegmentPercent.toFixed(3)}`),this.clickToSegmentIsGrowing=!0,this.doClickToSegment({x:h,y:u,tileIndex:m}));return}const c=this.canvas.getBoundingClientRect(),l=i.clientX-c.left,d=i.clientY-c.top;if(this.getCurrentDragMode()===3&&this.inRenderTile(this.uiData.dpr*l,this.uiData.dpr*d)===-1){const h=r<0?1:-1;let u=this.scene.pan2Dxyzmm[3]*(1+10*(.01*h));u=Math.round(u*10)/10;const m=this.scene.pan2Dxyzmm[3]-u;this.opts.yoke3Dto2DZoom&&(this.scene.volScaleMultiplier=u),this.scene.pan2Dxyzmm[3]=u;const g=this.frac2mm(this.scene.crosshairPos);this.scene.pan2Dxyzmm[0]+=m*g[0],this.scene.pan2Dxyzmm[1]+=m*g[1],this.scene.pan2Dxyzmm[2]+=m*g[2],this.drawScene(),this.canvas.focus(),this.sync();return}this.sliceScroll2D(r,l,d)}registerInteractions(){if(!this.canvas)throw new Error("canvas undefined");pn(this,Hn,new AbortController);const{signal:i}=dt(this,Hn);this.canvas.addEventListener("mousedown",this.mouseDownListener.bind(this),{signal:i}),this.canvas.addEventListener("mouseup",this.mouseUpListener.bind(this),{signal:i}),this.canvas.addEventListener("mousemove",this.mouseMoveListener.bind(this),{signal:i}),this.canvas.addEventListener("mouseleave",this.mouseLeaveListener.bind(this),{signal:i}),this.canvas.addEventListener("touchstart",this.touchStartListener.bind(this),{signal:i}),this.canvas.addEventListener("touchend",this.touchEndListener.bind(this),{signal:i}),this.canvas.addEventListener("touchmove",this.touchMoveListener.bind(this),{signal:i}),this.canvas.addEventListener("wheel",this.wheelListener.bind(this),{signal:i}),this.canvas.addEventListener("contextmenu",this.mouseContextMenuListener.bind(this),{signal:i}),this.canvas.addEventListener("dblclick",this.resetBriCon.bind(this),{signal:i}),this.canvas.addEventListener("dragenter",this.dragEnterListener.bind(this),{signal:i}),this.canvas.addEventListener("dragover",this.dragOverListener.bind(this),{signal:i}),this.canvas.addEventListener("drop",t=>{this.dropListener(t).catch(console.error)},{signal:i}),this.canvas.setAttribute("tabindex","0"),this.canvas.addEventListener("keyup",this.keyUpListener.bind(this),{signal:i}),this.canvas.addEventListener("keydown",this.keyDownListener.bind(this),{signal:i})}dragEnterListener(i){i.stopPropagation(),i.preventDefault()}dragOverListener(i){i.stopPropagation(),i.preventDefault()}getFileExt(i,t=!0){k.debug("fullname: ",i);const n=/(?:\.([^.]+))?$/;let s=n.exec(i)[1];if(s=s.toUpperCase(),s==="GZ")s=n.exec(i.slice(0,-3))[1],s=s.toUpperCase();else if(s==="CBOR"){const r=s;s=n.exec(i.slice(0,-5))[1],s=s.toUpperCase(),s=`${s}.${r}`}return t?s:s.toLowerCase()}async addVolumeFromUrl(i){const t=await Ue.loadFromUrl(i);return this.document.addImageOptions(t,i),t.onColormapChange=this.onColormapChange,this.mediaUrlMap.set(t,i.url),this.onVolumeAddedFromUrl&&this.onVolumeAddedFromUrl(i,t),this.addVolume(t),t}async addVolumesFromUrl(i){const t=i.map(async s=>{const r=this.getFileExt(s.name||s.url);if(r==="DCM")throw new Error("DICOM files must be loaded using useDicomLoader");if(this.loaders[r]){let d=s.url;const h=this.loaders[r].toExt;let u=s.name||s.url;if(u=u.split("/").pop(),typeof s.url=="string"){const g=s.url;try{const A=await fetch(g);if(!A.ok)throw new Error(`Failed to load file: ${A.statusText}`);d=await A.arrayBuffer()}catch(A){throw new Error(`Failed to load url ${g}: ${A}`)}}const m=await this.loaders[r].loader(d);s.url=m,s.name=`${u}.${h}`}const c={url:s.url,headers:s.headers,name:s.name,colormap:s.colormap?s.colormap:s.colorMap,colormapNegative:s.colormapNegative?s.colormapNegative:s.colorMapNegative,opacity:s.opacity,urlImgData:s.urlImgData,cal_min:s.cal_min,cal_max:s.cal_max,trustCalMinMax:this.opts.trustCalMinMax,isManifest:s.isManifest,frame4D:s.frame4D,limitFrames4D:s.limitFrames4D||this.opts.limitFrames4D,colorbarVisible:s.colorbarVisible},l=await Ue.loadFromUrl(c);return this.document.addImageOptions(l,c),l.onColormapChange=this.onColormapChange,this.mediaUrlMap.set(l,c.url),this.onVolumeAddedFromUrl&&this.onVolumeAddedFromUrl(c,l),l}),n=await Promise.all(t);for(let s=0;st[1]===i).map(t=>t[0]).pop()}removeVolumeByUrl(i){const t=this.getMediaByUrl(i);if(t)this.removeVolume(t);else throw new Error("No volume with URL present")}async traverseFileTree(i,t="",n){return new Promise(s=>{if(i.isFile)i.file(r=>{r.fullPath=t+r.name,r._webkitRelativePath=t+r.name,n.push(r),s(n)});else if(i.isDirectory){const r=i.createReader(),c=()=>{r.readEntries(l=>{if(l.length>0){const d=[];for(const h of l)d.push(this.traverseFileTree(h,t+i.name+"/",n));Promise.all(d).then(c).catch(h=>{throw h})}else s(n)})};c()}})}readDirectory(i){const t=i.createReader();let n=[];const s=async c=>{const l=[],d=async h=>new Promise((u,m)=>h.file(u,m));for(let h=0;h{t.readEntries(c=>{c.length?(n=n.concat(c),r()):s(n).then(async()=>{}).catch(l=>{throw l})})};return r(),n}isMeshExt(i){const t=this.getFileExt(i);return k.debug("dropped ext"),k.debug(t),Yn.includes(t)}async loadFromArrayBuffer(i,t){const n=this.getFileExt(t);if(Yn.includes(n)){await this.addMeshFromUrl({url:t,buffer:i});return}const s=Gl(t);s.buffer=i,s.name=t,await this.addVolumeFromUrl(s)}async loadFromFile(i){const t=this.getFileExt(i.name);if(Yn.includes(t)){await Gs.loadFromFile({file:i,gl:this.gl,name:i.name}).then(n=>{this.addMesh(n)});return}await Ue.loadFromFile({file:i,name:i.name}).then(n=>{this.addVolume(n)})}useLoader(i,t,n){this.loaders={...this.loaders,[t.toUpperCase()]:{loader:i,toExt:n}}}useDicomLoader(i){this.dicomLoader=i}getDicomLoader(){return this.dicomLoader}async dropListener(i){if(this.eventInBounds(i))this.opts.bounds&&(this.opts.showBoundsBorder=!0);else{this.opts.showBoundsBorder=!1;return}if(i.stopPropagation(),i.preventDefault(),!this.opts.dragAndDropEnabled)return;const t=[],n=i.dataTransfer;if(!n)return;const s=n.getData("text/uri-list");if(s){const r=Gl(s),c=this.getFileExt(s);k.debug("dropped ext"),k.debug(c),Yn.includes(c)?this.addMeshFromUrl({url:s}).catch(l=>{throw l}):c==="NVD"?this.loadDocumentFromUrl(s).catch(l=>{throw l}):this.addVolumeFromUrl(r).catch(l=>{throw l})}else{const r=n.items;if(r.length>0){!i.shiftKey&&!i.altKey&&(this.volumes=[],this.overlays=[],this.meshes=[]),this.closeDrawing(),this.closePAQD();for(const c of Array.from(r)){const l=c.webkitGetAsEntry();if(k.debug(l),!l)throw new Error("could not get entry from file");if(l.isFile){const d=this.getFileExt(l.name);let h;if(l.name.lastIndexOf("HEAD")!==-1)for(const u of Array.from(r)){const m=u.webkitGetAsEntry();if(!m)throw new Error("could not get paired entry");const g=l.name.substring(0,l.name.lastIndexOf("HEAD")),A=m.name.substring(0,m.name.lastIndexOf("BRIK"));g===A&&(h=m)}if(l.name.toUpperCase().lastIndexOf("HDR")!==-1)for(const u of Array.from(r)){const m=u.webkitGetAsEntry();if(!m)throw new Error("could not get paired entry");const g=l.name.substring(0,l.name.toUpperCase().lastIndexOf("HDR")),A=m.name.substring(0,m.name.toUpperCase().lastIndexOf("IMG"));g===A&&(h=m)}if(l.name.lastIndexOf("BRIK")!==-1||l.name.toUpperCase().lastIndexOf("IMG")!==-1)continue;if(this.loaders[d]){const u=await Bv(l);await this.loadImages([{url:u,name:`${l.name}`}]);continue}if(Yn.includes(d)){l.file(u=>{(async()=>{try{const m=await Gs.loadFromFile({file:u,gl:this.gl,name:u.name});this.addMesh(m)}catch(m){console.error("Error loading mesh:",m)}})().catch(m=>console.error(m))});continue}else if(d==="NVD"){l.file(u=>{(async()=>{try{const m=await Bh.loadFromFile(u);await this.loadDocument(m),k.debug("loaded document")}catch(m){console.error(m)}})().catch(m=>console.error(m))});break}l.file(u=>{(async()=>{try{if(h)h.file(m=>{(async()=>{try{const g=await Ue.loadFromFile({file:u,urlImgData:m,limitFrames4D:this.opts.limitFrames4D});this.addVolume(g)}catch(g){console.error(g)}})().catch(console.error)});else{const m=await Ue.loadFromFile({file:u,urlImgData:h,limitFrames4D:this.opts.limitFrames4D});i.altKey?(k.debug("alt key detected: assuming this is a drawing overlay"),this.drawClearAllUndoBitmaps(),this.loadDrawing(m)):this.addVolume(m)}}catch(m){console.error(m)}})().catch(console.error)})}else l.isDirectory&&this.traverseFileTree(l,"",t).then(d=>{const h=this.getDicomLoader().loader;if(!h)throw new Error("No loader for DICOM files");h(d).then(async u=>{const m=u.map(g=>Ue.loadFromUrl({url:g.data,name:g.name,limitFrames4D:this.opts.limitFrames4D}));Promise.all(m).then(async g=>{await this.onDicomLoaderFinishedWithImages(g)}).catch(g=>{throw g})}).catch(u=>{console.error("Error loading DICOM files:",u)})}).catch(d=>{throw d})}}}this.drawScene()}setMultiplanarPadPixels(i){this.opts.multiplanarPadPixels=i,this.drawScene()}setMultiplanarLayout(i){typeof i=="string"&&(i=parseInt(i)),this.opts.multiplanarLayout=i,this.drawScene()}setCornerOrientationText(i){this.opts.isCornerOrientationText=i,this.updateGLVolume()}setIsOrientationTextVisible(i){this.opts.isOrientationTextVisible=i,this.drawScene()}setShowAllOrientationMarkers(i){this.opts.showAllOrientationMarkers=i,this.drawScene()}setHeroImage(i){this.opts.heroImageFraction=i,this.drawScene()}setCustomLayout(i){for(let t=0;tu,b=sm;if(w&&b)throw new Error(`Custom layout is invalid. Tile ${t} overlaps with tile ${h}.`)}}this.customLayout=i,this.drawScene()}clearCustomLayout(){this.customLayout=null,this.drawScene()}getCustomLayout(){return this.customLayout}setRadiologicalConvention(i){this.opts.isRadiologicalConvention=i,this.updateGLVolume()}setDefaults(i={},t=!1){this.document.opts={...mi},this.scene.sceneData={...Za};for(const n in i)typeof i[n]=="function"?this[n]=i[n]:this.opts[n]=mi[n]===void 0?mi[n]:i[n];if(this.scene.pan2Dxyzmm=[0,0,0,1],t&&this.volumes&&this.volumes.length>0)for(let n=0;n{}}addVolume(i){this.volumes.push(i);const t=this.volumes.length===1?0:this.volumes.length-1;this.setVolume(i,t),this.onImageLoaded(i),k.debug("loaded volume",i.name),k.debug(i)}addMesh(i){this.meshes.push(i);const t=this.meshes.length===1?0:this.meshes.length-1;this.setMesh(i,t),this.onMeshLoaded(i)}getVolumeIndexByID(i){const t=this.volumes.length;for(let n=0;n0){const t=this.drawBitmap.length,n=Wh(this.drawUndoBitmaps[this.currentDrawUndoBitmap],t);for(let s=0;s0&&(this.drawBitmap[s]=n[s]);this.refreshDrawing(!1)}this.currentDrawUndoBitmap++,this.currentDrawUndoBitmap>=this.opts.maxDrawUndoBitmaps&&(this.currentDrawUndoBitmap=0),this.drawUndoBitmaps[this.currentDrawUndoBitmap]=S4(this.drawBitmap)}drawClearAllUndoBitmaps(){if(this.currentDrawUndoBitmap=this.opts.maxDrawUndoBitmaps,!(!this.drawUndoBitmaps||this.drawUndoBitmaps.length<1))for(let i=this.drawUndoBitmaps.length-1;i>=0;i--)this.drawUndoBitmaps[i]=new Uint8Array}drawUndo(){const{drawBitmap:i,currentDrawUndoBitmap:t}=M4({drawUndoBitmaps:this.drawUndoBitmaps,currentDrawUndoBitmap:this.currentDrawUndoBitmap,drawBitmap:this.drawBitmap});this.drawBitmap=i,this.currentDrawUndoBitmap=t,this.refreshDrawing(!0)}loadDrawing(i){if(this.drawBitmap&&k.debug("Overwriting open drawing!"),!this.back)throw new Error("back undefined");this.drawClearAllUndoBitmaps();const t=i.hdr.dims;if(t[1]!==this.back.hdr.dims[1]||t[2]!==this.back.hdr.dims[2]||t[3]!==this.back.hdr.dims[3])return k.debug("drawing dimensions do not match background image"),!1;i.img.constructor!==Uint8Array&&k.debug("Drawings should be UINT8");const n=i.permRAS,s=t[1]*t[2]*t[3];this.drawBitmap=new Uint8Array(s),this.opts.is2DSliceShader?this.drawTexture=this.r8Tex2D(this.drawTexture,gn,this.back.dims,!0):this.drawTexture=this.r8Tex(this.drawTexture,gn,this.back.dims,!0);const r=[0,0,0];for(let y=0;y<3;y++)for(let w=0;w<3;w++)Math.abs(n[y])-1===w&&(r[w]=y*Math.sign(n[y]));let c=1;const l=[1,1,1],d=[!1,!1,!1];for(let y=0;yArray(s).fill(0)),y=Array(s).fill(0).map(()=>Array(s).fill(0));for(let C=1;C3)for(let C=0;Cw&&(b[0]=C,b[1]=S,b[2]=E,w=M)}else if(i===3)for(let C=0;Cw&&(b[0]=C,b[1]=S,w=E)}else for(let C=0;Cw&&(b[0]=C,w=S)}return[u(b[0]),u(b[1]),u(b[2])]}drawOtsu(i=2){if(this.volumes.length===0)return;const t=this.volumes[0].img.length,n=this.findOtsu(i);if(n.length<3)return;this.drawBitmap||this.createEmptyDrawing();const s=this.drawBitmap,r=this.volumes[0].img;for(let c=0;cn[0]&&(s[c]=1),l>n[1]&&(s[c]=2),l>n[2]&&(s[c]=3)}this.drawAddUndoBitmap(),this.refreshDrawing(!0)}removeHaze(i=5,t=0){const n=this.volumes[t].img,s=this.volumes[t].hdr,r=n.length;let c=2;(i===5||i===1)&&(c=4),(i===4||i===2)&&(c=3);const l=this.findOtsu(c);if(l.length<3)return;let d=l[0];i===1&&(d=l[2]),i===2&&(d=l[1]);const h=s.scl_inter,u=s.scl_slope,m=this.volumes[t].global_min;for(let g=0;g=this.meshes.length?-1:i;const t=this.meshes.length;for(let n=0;nn)return;const s=this.getVolumeIndexByID(i.id);t===0?(this.volumes.splice(s,1),this.volumes.unshift(i),this.back=this.volumes[0],this.overlays=this.volumes.slice(1)):t<0?(this.volumes.splice(this.getVolumeIndexByID(i.id),1),this.back=this.volumes[0],this.volumes.length>1?this.overlays=this.volumes.slice(1):this.overlays=[]):(this.volumes.splice(s,1),this.volumes.splice(t,0,i),this.overlays=this.volumes.slice(1),this.back=this.volumes[0]),this.updateGLVolume()}setMesh(i,t=0){this.meshes.forEach(r=>{k.debug("MESH: ",r.name)});const n=this.meshes.length;if(t>n)return;const s=this.getMeshIndexByID(i.id);t===0?(this.meshes.splice(s,1),this.meshes.unshift(i)):t<0?this.meshes.splice(this.getMeshIndexByID(i.id),1):(this.meshes.splice(s,1),this.meshes.splice(t,0,i)),this.updateGLVolume(),this.meshes.forEach(r=>{k.debug(r.name)})}removeVolume(i){if(this.setVolume(i,-1),this.mediaUrlMap.has(i)){const t=this.mediaUrlMap.get(i);this.onVolumeWithUrlRemoved(t),this.mediaUrlMap.delete(i)}this.drawScene()}removeVolumeByIndex(i){if(i>=this.volumes.length)throw new Error("Index of volume out of bounds");this.removeVolume(this.volumes[i])}removeMesh(i){if(i.unloadMesh(this.gl),this.setMesh(i,-1),this.mediaUrlMap.has(i)){const t=this.mediaUrlMap.get(i);this.onMeshWithUrlRemoved(t),this.mediaUrlMap.delete(i)}}removeMeshByUrl(i){const t=this.getMediaByUrl(i);t&&(this.removeMesh(t),this.mediaUrlMap.delete(t),this.onMeshWithUrlRemoved(i))}moveVolumeToBottom(i){this.setVolume(i,0)}moveVolumeUp(i){const t=this.getVolumeIndexByID(i.id);this.setVolume(i,t+1)}moveVolumeDown(i){const t=this.getVolumeIndexByID(i.id);this.setVolume(i,t-1)}moveVolumeToTop(i){this.setVolume(i,this.volumes.length-1)}mouseDown(i,t){i*=this.uiData.dpr,t*=this.uiData.dpr,this.mousePos=[i,t]}updateMousePos(i,t){return i*=this.uiData.dpr,t*=this.uiData.dpr,this.mousePos=[i,t],[i,t]}mouseMove(i,t){i*=this.uiData.dpr,t*=this.uiData.dpr;const n=(i-this.mousePos[0])/this.uiData.dpr,s=(t-this.mousePos[1])/this.uiData.dpr;this.mousePos=[i,t],!(this.inRenderTile(i,t)<0)&&(Math.abs(n)<1&&Math.abs(s)<1||(this.scene.renderAzimuth+=n,this.scene.renderElevation+=s,this.drawScene()))}sph2cartDeg(i,t){const n=-t*(Math.PI/180),s=(i-90)%360*(Math.PI/180),r=[Math.cos(n)*Math.cos(s),Math.cos(n)*Math.sin(s),Math.sin(n)],c=Math.sqrt(r[0]*r[0]+r[1]*r[1]+r[2]*r[2]);return c<=0||(r[0]/=c,r[1]/=c,r[2]/=c),r}setClipPlanes(i){this.scene.clipPlanes=[],this.scene.clipPlaneDepthAziElevs=[];for(let t=0;t0&&r++,i<0&&r--,this.setFrame4D(this.volumes[0].id,r);return}if(i!==0&&this.opts.dragMode===3&&this.inRenderTile(this.uiData.dpr*t,this.uiData.dpr*n)===-1){let r=this.scene.pan2Dxyzmm[3]*(1+10*i);r=Math.round(r*10)/10;const c=this.scene.pan2Dxyzmm[3]-r;this.opts.yoke3Dto2DZoom&&(this.scene.volScaleMultiplier=r),this.scene.pan2Dxyzmm[3]=r;const l=this.frac2mm(this.scene.crosshairPos);this.scene.pan2Dxyzmm[0]+=c*l[0],this.scene.pan2Dxyzmm[1]+=c*l[1],this.scene.pan2Dxyzmm[2]+=c*l[2],this.drawScene(),this.canvas.focus(),this.sync();return}this.mouseClick(t,n,i,s)}setSliceType(i){return this.opts.sliceType=i,this.drawScene(),this}setOpacity(i,t){this.volumes[i].opacity=t,this.updateGLVolume()}setScale(i){this.scene.volScaleMultiplier=i,this.drawScene()}setClipPlaneColor(i){this.opts.clipPlaneColor=i,this.renderShader.use(this.gl),this.gl.uniform4fv(this.renderShader.uniforms.clipPlaneColor,this.opts.clipPlaneColor),this.drawScene()}setClipPlaneThick(i){k.warn("setClipPlaneThick() has been removed. use setClipPlanes() instead.")}setClipVolume(i,t){k.warn("setClipVolume() has been removed. use setClipPlanes() instead.")}async setVolumeRenderIllumination(i=0){this.renderGradientValues=Number.isNaN(i),this.renderShader=this.renderVolumeShader,this.renderGradientValues?this.renderShader=this.renderGradientValuesShader:(this.opts.gradientAmount=i,i>0||this.opts.gradientOpacity>0?this.renderShader=this.renderGradientShader:i<0&&(this.renderShader=this.renderSliceShader)),await this.refreshLayers(this.volumes[0],0),this.initRenderShader(this.renderShader,i),this.renderShader.use(this.gl),this.setClipPlaneColor(this.opts.clipPlaneColor),Number.isNaN(i)?this.gradientTextureAmount=1:this.gradientTextureAmount=i,!(this.volumes.length<1)&&this.drawScene()}async setGradientOpacity(i=0,t=0){this.opts.gradientOpacity=i,this.opts.renderSilhouette=t,this.renderGradientValues?this.renderShader=this.renderGradientValuesShader:this.gradientTextureAmount>0||i>0?this.renderShader=this.renderGradientShader:this.gradientTextureAmount<0&&(this.renderShader=this.renderSliceShader),this.initRenderShader(this.renderShader,this.gradientTextureAmount),this.renderShader.use(this.gl),this.gradientTextureAmount>0&&this.refreshLayers(this.volumes[0],0),this.drawScene()}overlayRGBA(i){const t=i.hdr,n=t.dims[1]*t.dims[2]*t.dims[3],s=new Uint8ClampedArray(n*4),r=.2*Math.min(Math.min(t.dims[1],t.dims[2]),t.dims[3]),c=.5*t.dims[1],l=.5*t.dims[2],d=.5*t.dims[3];let h=0;for(let u=0;u0&&(this.back=this.volumes[0]);for(const r of i.meshDataObjects??[]){const c={gl:this.gl,...r};r.offsetPt0&&(c.rgba255[3]=0,c.tris=new Uint32Array(r.offsetPt0)),k.debug(c);const l=new Gs(c.pts,c.tris,c.name,c.rgba255,c.opacity,c.visible,this.gl,c.connectome,c.dpg,c.dps,c.dpv);r.offsetPt0&&(l.fiberGroupColormap=r.fiberGroupColormap,l.fiberColor=r.fiberColor,l.fiberDither=r.fiberDither,l.fiberRadius=r.fiberRadius,l.colormap=r.colormap),l.meshShaderIndex=c.meshShaderIndex,l.layers=c.layers,l.updateMesh(this.gl),k.debug(l),this.addMesh(l)}if(i.data.connectomes)for(const r of i.data.connectomes){const c=JSON.parse(r),l=this.loadConnectomeAsMesh(c);l.updateMesh(this.gl),this.addMesh(l)}this.createEmptyDrawing();const s=i.encodedDrawingBlob;if(s){const r=await At.b64toUint8(s);if(r){const c=this.back.dims;let l=c[1]*c[2]*c[3];if(r.length-352===l&&(l+=352),r.length!==l)throw new Error(`drawBitmap size does not match the texture dimensions (${c[1]}×${c[2]}×${c[3]}) ${l} != ${c[1]*c[2]*c[3]}.`);this.drawBitmap=r,this.refreshDrawing()}}return await this.setGradientOpacity(this.opts.gradientOpacity),await this.setVolumeRenderIllumination(this.opts.gradientAmount),this.updateGLVolume(),this.drawScene(),this.onDocumentLoaded(i),this}async generateLoadDocumentJavaScript(i,t){const n=this.json(),s=await At.compressToBase64String(JSON.stringify(n));return` + ${t} + + async function saveNiivueAsHtml(pageName) { + //get new docstring + const docString = nv1.json(); + const html = + document.getElementsByTagName("html")[0] + .innerHTML.replace(base64, await NVUtilities.compressToBase64String(JSON.stringify(docString))); + NVUtilities.download(html, pageName, "application/html"); + } + + var nv1 = new Niivue(); + await nv1.attachTo("${i}"); + var base64 = "${s}"; + NVUtilities.decompressBase64String(base64).then((jsonText) => { + var json = JSON.parse(jsonText); // string -> JSON + var doc = NVDocument.loadFromJSON(json); + nv1.loadDocument(doc); + nv1.updateGLVolume(); + }); + + `}async generateHTML(i="gl1",t){return` + + + + + + Save as HTML + + + + +
+ Save the current scene as HTML + +
+
+ +
+